{"version":3,"sources":["app.js","../Client/app/di/token.ts","../Client/app/di/decorators.ts","../Client/app/helpers/dirs.ts","../Client/app/helpers/clara-scene.service.ts","../Client/app/helpers/state.helper.ts","../Client/app/animations/kb-rise.animation.ts","../Client/app/components/directive.ts","../Client/app/components/kb-action-select/kb-action-select.component.ts","../Client/app/components/kb-allow-fractions/kb-allow-fractions.component.ts","../Client/app/components/kb-atom/kb-atom.component.ts","../Client/app/components/kb-attachments/kb-attachments.component.ts","../Client/app/components/kb-input/kb-input.component.ts","../Client/app/components/kb-auto-complete/kb-auto-complete.component.ts","../Client/app/components/kb-avatar-select/kb-avatar-select.component.ts","../Client/app/components/kb-avatar/kb-avatar.component.ts","../Client/app/components/kb-button/kb-button.component.ts","../Client/app/components/kb-checkbox/kb-checkbox.component.ts","../Client/app/components/kb-color-picker/kb-color-picker.component.ts","../Client/app/components/kb-column/kb-column.component.ts","../Client/app/components/kb-comments/kb-comments.component.ts","../Client/app/components/kb-content/kb-content.component.ts","../Client/app/components/kb-data-grid/kb-data-grid.component.ts","../Client/app/components/kb-date-picker/kb-date-picker.component.ts","../Client/app/components/kb-dropdown/kb-dropdown.component.ts","../Client/app/components/kb-edit/kb-edit.component.ts","../Client/app/components/kb-ellipsis/kb-ellipsis.component.ts","../Client/app/components/kb-expander/kb-expander-group.component.ts","../Client/app/components/kb-expander/kb-expander.component.ts","../Client/app/components/kb-field/kb-field.component.ts","../Client/app/components/kb-focus/kb-focus.component.ts","../Client/app/components/kb-form/kb-form.component.ts","../Client/app/components/kb-icon/kb-icon.component.ts","../Client/app/components/kb-if/kb-if.component.ts","../Client/app/components/kb-if-delay/kb-if-delay.component.ts","../Client/app/components/kb-multi-select/kb-multi-select.component.ts","../Client/app/helpers/image-select.helper.ts","../Client/app/components/kb-image-multi-select/kb-image-multi-select.component.ts","../Client/app/components/kb-image-select/kb-image-select.component.ts","../Client/app/components/kb-include/kb-include.component.ts","../Client/app/components/kb-infinite-scroll/kb-infinite-scroll.component.ts","../Client/app/components/kb-label/kb-label.component.ts","../Client/app/components/kb-list/kb-list-item.component.ts","../Client/app/components/kb-list/kb-list.component.ts","../Client/app/components/kb-markdown-viewer/kb-markdown-viewer.component.ts","../Client/app/components/kb-max/kb-max.component.ts","../Client/app/components/kb-media-list/kb-media-list.component.ts","../Client/app/components/kb-media-manager/kb-media-manager.component.ts","../Client/app/components/kb-media-select/kb-media-select.component.ts","../Client/app/components/kb-media-viewer/kb-media-viewer.component.ts","../Client/app/components/kb-menu/kb-menu-item.component.ts","../Client/app/components/kb-menu/kb-menu.component.ts","../Client/app/components/kb-min/kb-min.component.ts","../Client/app/components/kb-money/kb-money.component.ts","../Client/app/components/kb-multi-auto-complete/kb-multi-auto-complete.component.ts","../Client/app/components/kb-numberbox/kb-numberbox.component.ts","../Client/app/components/kb-page-title/kb-page-title.component.ts","../Client/app/components/kb-page/kb-page.component.ts","../Client/app/components/kb-password/kb-password.component.ts","../Client/app/components/kb-privacy-policy/kb-privacy-policy.component.ts","../Client/app/components/kb-progress/kb-progress.component.ts","../Client/app/components/kb-radio/kb-radio.component.ts","../Client/app/components/kb-resize/kb-resize.component.ts","../Client/app/components/kb-ripple/kb-ripple.component.ts","../Client/app/components/kb-scope/kb-scope.component.ts","../Client/app/components/kb-search-grid/kb-search-grid.component.ts","../Client/app/components/kb-select/kb-select.component.ts","../Client/app/components/kb-sfdc-header/kb-sfdc-header.component.ts","../Client/app/components/kb-slide/kb-slide.component.ts","../Client/app/components/kb-slider/kb-slider.component.ts","../Client/app/components/kb-spinner/kb-spinner-element.component.ts","../Client/app/components/kb-spinner/kb-spinner.component.ts","../Client/app/components/kb-src-on-error/kb-src-on-error.component.ts","../Client/app/components/kb-svg-viewer/kb-svg-viewer.component.ts","../Client/app/components/kb-tabs/kb-tab.component.ts","../Client/app/components/kb-tabs/kb-tabs.component.ts","../Client/app/components/kb-textbox/kb-textbox.component.ts","../Client/app/components/kb-text-area/kb-textarea.component.ts","../Client/app/components/kb-toggle/kb-toggle.component.ts","../Client/app/components/kb-tooltip/kb-tooltip.component.ts","../Client/app/components/kb-transclude/kb-transclude.component.ts","../Client/app/components/kb-tree/kb-tree-node.component.ts","../Client/app/components/kb-tree/kb-tree.component.ts","../Client/app/components/kb-ui-object/kb-ui-object.component.ts","../Client/app/components/kb-upload/kb-upload.component.ts","../Client/app/components/kb-validation-messages/kb-validation-messages.component.ts","../Client/app/filters/asset.filter.ts","../Client/app/filters/bytes.filter.ts","../Client/app/filters/enum.filter.ts","../Client/app/filters/file-icon.filter.ts","../Client/app/filters/file-id.filter.ts","../Client/app/filters/fx-convert.filter.ts","../Client/app/filters/get-file-extension.filter.ts","../Client/app/filters/get-filename.filter.ts","../Client/app/filters/has-role.filter.ts","../Client/app/filters/icon.filter.ts","../Client/app/filters/is-admin-or-company-admin.filter.ts","../Client/app/filters/kb-currency.filter.ts","../Client/app/filters/kb-date-time.filter.ts","../Client/app/filters/kb-date.filter.ts","../Client/app/filters/lead-time.filter.ts","../Client/app/filters/loc.filter.ts","../Client/app/filters/log-icon.filter.ts","../Client/app/filters/media.filter.ts","../Client/app/filters/notification-icon.filter.ts","../Client/app/filters/number-format.filter.ts","../Client/app/filters/profile-image.filter.ts","../Client/app/filters/quote-product-image.filter.ts","../Client/app/filters/range.filter.ts","../Client/app/filters/raw-text.filter.ts","../Client/app/filters/shade.filter.ts","../Client/app/filters/smart-color.filter.ts","../Client/app/filters/theme-color.filter.ts","../Client/app/filters/thumb.filter.ts","../Client/app/filters/truncate.filter.ts","../Client/app/filters/trust-as-html.filter.ts","../Client/app/views/portal/login.view.ts","../Client/app/helpers/scene-viewer.ts","../Client/app/helpers/clara-viewer.ts","../Client/app/helpers/configurator.helper.ts","../Client/app/helpers/kb3d-viewer.ts","../Client/app/interceptors/cache-buster.interceptor.ts","../Client/app/interceptors/error.interceptor.ts","../Client/app/interceptors/security.interceptor.ts","../Client/app/services/api.service.ts","../Client/app/services/auth.service.ts","../Client/app/services/base64.service.ts","../Client/app/services/bundle-loader.service.ts","../Client/app/services/crud.service.ts","../Client/app/services/dialog.service.ts","../Client/app/services/drawer.service.ts","../Client/app/services/interaction.service.ts","../Client/app/services/kb.service.ts","../Client/app/services/quote.service.ts","../Client/app/services/rule.service.ts","../Client/app/services/search.service.ts","../Client/app/services/security-retry.service.ts","../Client/app/services/sfdc.service.ts","../Client/app/services/signalr.service.ts","../Client/app/services/storage.service.ts","../Client/app/services/telemetry.service.ts","../Client/app/services/theme.service.ts","../Client/app/services/upload.service.ts","../Client/app/views/base.view.ts","../Client/app/views/crud.view.ts","../Client/app/views/contacts/contact.view.ts","../Client/app/views/search.view.ts","../Client/app/views/contacts/contacts.view.ts","../Client/app/views/customers/customer.view.ts","../Client/app/views/customers/customers.view.ts","../Client/app/views/dialog/dialog.view.ts","../Client/app/views/notifications/notifications.view.ts","../Client/app/views/portal/drawer.view.ts","../Client/app/views/portal/portal.view.ts","../Client/app/views/portal/privacypolicy.view.ts","../node_modules/qrcode/lib/can-promise.js","../node_modules/qrcode/lib/core/utils.js","../node_modules/qrcode/lib/core/error-correction-level.js","../node_modules/qrcode/lib/core/bit-buffer.js","../node_modules/qrcode/lib/core/bit-matrix.js","../node_modules/qrcode/lib/core/alignment-pattern.js","../node_modules/qrcode/lib/core/finder-pattern.js","../node_modules/qrcode/lib/core/mask-pattern.js","../node_modules/qrcode/lib/core/error-correction-code.js","../node_modules/qrcode/lib/core/galois-field.js","../node_modules/qrcode/lib/core/polynomial.js","../node_modules/qrcode/lib/core/reed-solomon-encoder.js","../node_modules/qrcode/lib/core/version-check.js","../node_modules/qrcode/lib/core/regex.js","../node_modules/qrcode/lib/core/mode.js","../node_modules/qrcode/lib/core/version.js","../node_modules/qrcode/lib/core/format-info.js","../node_modules/qrcode/lib/core/numeric-data.js","../node_modules/qrcode/lib/core/alphanumeric-data.js","../node_modules/qrcode/lib/core/byte-data.js","../node_modules/encode-utf8/index.js","../node_modules/qrcode/lib/core/kanji-data.js","../node_modules/dijkstrajs/dijkstra.js","../node_modules/qrcode/lib/core/segments.js","../node_modules/qrcode/lib/core/qrcode.js","../node_modules/qrcode/lib/renderer/utils.js","../node_modules/qrcode/lib/renderer/canvas.js","../node_modules/qrcode/lib/renderer/svg-tag.js","../node_modules/qrcode/lib/browser.js","../Client/app/views/users/user-activation.view.ts","../Client/app/views/products/configurator.view.ts","../Client/app/views/products/product-compare.view.ts","../Client/app/views/products/product.view.ts","../Client/app/views/products/products.view.ts","../Client/app/views/quotes/configured-products.view.ts","../Client/app/views/quotes/quote.view.ts","../Client/app/views/quotes/quotes.view.ts","../Client/app/views/users/change-password.view.ts","../Client/app/views/users/user.view.ts","../Client/app/app.ts"],"names":["app","exports","enums","angular","_tools","flatpickr","Tether","_rules","kb3d","Q","signalR","Big","_interopDefaultLegacy","e","default","_interopNamespace","__esModule","n","Object","create","keys","forEach","k","d","getOwnPropertyDescriptor","defineProperty","get","enumerable","freeze","enums__namespace","flatpickr__default","Tether__default","Q__namespace","Big__default","Token","key","this","withKey","token","AdminLib","Creator","HandsontableLib","HighchartsLib","MarkdownDeepLib","MonacoLoaderLib","Recaptcha","SnapLib","Viewer","$Animate","$Scope","$Location","$Http","$RootScope","$Timeout","$Q","$Window","$Document","$Filter","$Injector","$Interval","$TemplateCache","$TemplateRequest","$Compile","$Sce","$Locale","$CookieStore","$Sanitize","PromiseTracker","$OcLazyLoad","$State","$Transitions","$StateParams","Model","ProductResolve","Categories","Header","SsoGroups","KbRise","KbActionSelect","KbAllowFraction","KbAtom","KbAttachments","KbAutoComplete","KbAvatar","KbAvatarSelect","KbButton","KbCheckbox","KbColorPicker","KbColumn","KbContent","KbComments","KbDataGrid","KbDatePicker","KbDropdown","KbEdit","KbEllipsis","KbExpander","KbExpanderGroup","KbField","KbFieldControl","KbFocus","KbForm","KbIcon","KbIf","KbIfDelay","KbImageSelect","KbInclude","KbInfiniteScroll","KbLabel","KbList","KbListItem","KbMarkdownViewer","KbMax","KbMediaList","KbMediaManager","KbMediaSelect","KbMediaViewer","KbMenu","KbMenuItem","KbMin","KbMoney","KbMultiAutoComplete","KbMultiSelect","KbImageMultiSelect","KbNumberbox","KbOption","KbPage","KbPageTitle","KbPassword","KbPrivacyPolicy","KbProgress","KbRadio","KbResize","KbRipple","KbScope","KbSearchGrid","KbSelect","KbSfdcHeader","KbSlide","KbSlider","KbSpinner","KbSpinnerElement","KbSrcOnError","KbSvgViewer","KbTab","KbTabs","KbTextarea","KbTextbox","KbToggle","KbToggleButton","KbTooltip","KbTransclude","KbTree","KbTreeNode","KbUiObject","KbUpload","KbValidationMessages","AssetFilter","BytesFilter","EnumFilter","FileIconFilter","FileIdFilter","FxConvertFilter","GetFileExtensionFilter","GetFilenameFilter","HasRoleFilter","IconFilter","IsAdminOrCompanyAdminFilter","KbCurrencyFilter","KbDateTimeFilter","KbDateFilter","LeadTimeFilter","LocFilter","LogIconFilter","MediaFilter","NotificationIconFilter","NumberFormateFilter","ProfileImageFilter","QuoteProductImageFilter","RangeFilter","RawTextFilter","ShadeFilter","SmartColorFilter","ThemeColorFilter","ThumbFilter","TruncateFilter","TrustAsHtmlFilter","CacheBusterInterceptor","ErrorInterceptor","SecurityInterceptor","ApiService","AuthService","Base64Service","BundleLoaderService","ClaraSceneService","CrudService","DialogService","DrawerService","KbService","QuoteService","RuleService","SearchService","SecurityRetryService","SfdcService","SignalRService","StorageService","TelemetryService","ThemeService","UploadService","InteractionService","ContactView","ContactsView","CrudView","CustomerView","CustomersView","DialogView","NotificationsView","DrawerView","LoginView","PortalView","PrivacyPolicyView","ConfiguratorView","ProductView","ProductsView","ProductCompareView","ConfiguredProductsView","QuoteView","QuotesView","SceneEmbedView","SearchView","ChangePasswordView","UserActivationView","UserView","NgService","args","target","DI","register","NgAnimation","NgComponent","NgInterceptor","NgFilter","NgView","eBundle","ngType","constructor","_a","_b","_c","db","hasOwnProperty","Error","concat","dependencies","resolves","libraries","inherit","_i","_d","length","baseToken","baseInject","unshift","apply","resolveObject","reduce","p","c","name","map","fn","bind","bundleLoader","load","ngInject","construct","a","arguments","__spreadArray","fillAngularApp","i","addedToApp","eClaraPropertyType","eHighlightType","Dirs","component","bundle","template","view","url","window","html","StateHelper","$stateProvider","prototype","getPluralName","plural","endsWith","slice","addState","o","_this","resolve","assign","kebab","split","last","toKebabCase","allowAnonymous","authService","authPromise","data","state","angular.isDefined","params","templateUrl","templateName","controller","reloadOnSearch","parent","addSearchState","nameSegment","search","dynamic","searchid","addCrudStates","nameKebab","pluralName","baseUrl","statePrefix","substring","lastIndexOf","editStatePrefix","isSnapBased","searchView","newStateConfig","viewType","eViewType","new","newStateParams","join","edit","$timeout","duration","distance","Math","max","min","show","element","done","origOpacity","css","removeClass","finalSetHeight","hasClass","autoHeight","height","animate","hide","beforeAddClass","className","enter","leave","__decorate","Directive","_super","$q","$http","call","restrict","scope","source","valueField","defaultLabel","icon","onAction","replace","link","atts","ngModel","_actionSelect","$watch","newValue","__extends","KbAllowFractions","require","elem","attr","ctrl","maxValidator","value","$eval","kbAllowFractions","round","$","val","$parsers","push","$formatters","transclude","display","_editMode","editMode","eventName","Utils","shortId","documentClick","is","contains","$apply","_editing","document","off","changeEditMode","_displayClick","$event","on","editAtt","$on","$rootScope","dialogService","uploadService","storageService","objectId","tableName","relationshipProperty","files","fileEntityPath","canChange","canAdd","downloadFile","user","canModifyAllAttachments","canAddAttachments","secureFileDownloadUrl","item","open","getMediaUrl","filePath","_uploadFile","description","callback","file","fileInfo","$new","model","fileName","canViewMedia","context","canModifyMedia","dialog","type","eInputDialogType","buttons","DialogButton","loc","ok","icons","submit","cancel","uploadNewAttachment","promptUserToChooseFile","accept","then","selectedFile","eFileSource","uploaded","selectMediaFile","mediaSelect","MediaDialogButton","success","selectedItem","media","displayDialog","newFileEntity","id","createdBy","createdByName","firstName","lastName","status","eFileStatus","complete","postUrl","deferred_1","defer","alert","promise","successMsg","uploadAttachment","result","extend","reject","evt","lengthComputable","notify","loaded","total","put","post","isFromMedia","delete","confirm","msg_confirmdelete","remove","KbInput","ngDisabled","ngModelOptions","ngChange","ngBlur","touched","ignoreField","textColor","backgroundColor","heightOverride","s","kbInputLinkFn","controllers","shouldFloat","isEmpty","ngModelCtrl","kbField","setShouldFloat","toString","ngModelPipelineCheckValue","setHasValue","Array","isArray","$viewChangeListeners","setFocused","_ngChange","el","find","which","blur","_setHasValue","hasValue","getLabel","editable","labelField","headerTemplate","itemStyle","throttle","minCharacters","placeholder","mobileDropdown","compile","input","_id","toStringSafe","getItemValue","getItemLabel","l","isEnabled","setLabelForValue","match","_matches","m","$viewValue","when","_label","$render","_itemMousedown","preventDefault","_select","hideDropdown","$setViewValue","_hint","suppressFocusEvent","focus","showDropdown","_dropdownOpen","_isActive","index","_activeIndex","getMatches","query","_inProgress","toLowerCase","startsWith","substr","finally","_focus","_blur","_inputChange","newIndex","moveUp","moveDown","buildItem","stopPropagation","kbService","$filter","apiService","userId","ngModelController","imgPath","clear","users","clearProfileImage","imagePath","$broadcast","events","avatarChanged","click","uploadProfileImage","path","newPath","Date","getTime","ngClick","inputId","isCheckbox","_checkboxId","minicolors","control","defaultValue","inline","letterCase","opacity","position","change","addClass","append","label","field","sortable","toggleSort","order","gridCtrl","addColumn","$parent","kbIf","getClass","getStyle","api","_comments","refresh","canViewComments","r","_delete","_model","text","_cancel","_addComment","newComment","idUser","body","createdByImagePath","_edit","msg","inputType","textArea","InputDialogButton","kbContent","$scope","$element","columns","column","some","event","minDate","maxDate","format","enableTime","picker","onChange","parseDate","setDate","oldValue","set","_clear","destroy","scrollTo","autoDirection","horizontalAlign","verticalAlign","width","ignoreClickOn","ignoreClickOnParent","timeouts","openIsDefined","hAlign","vAlign","vAlignOpposite","isVisible","tether","scrollToActive","$item","scrollIntoView","mode","eScrollMode","middleIfNecessary","preventScroll","setTimeout","removeEventListener","onDocumentClicked","$target","parents","tetherZeroElem","querySelector","parentElement","removeChild","options","attachment","targetAttachment","constraints","to","pin","classes","enabled","closest","bodyElement","createTether","parentWidth","getBoundingClientRect","maxWidth","addEventListener","t","_click","_keydown","keyCode","keyboard","accordion","$attrs","_expanders","registerExpander","expander","expanded","updateExpanders","expand","activeExpander","title","expandedChanged","invalid","image","kbExpanderGroup","_toggle","newVal","oldVal","required","labelLoc","desc","descLoc","validationErrors","runFixThis","warnings","fixOptions","helpMedia","helpUrl","mobileHelpDropdown","useZeroPadding","focused","_focused","toggleClass","_hasValue","kbForm","modelProp_1","$input","first","autoLoc","modelType","autoDesc","validation","_runFixThis","f","fix","$animate","watchAtt","priority","terminal","$$tlb","$transclude","innerScope","innerElement","tempClasses","oVal","$resume","sc","after","hideDelay","$$postDigest","$suspend","$window","addItem","removeItem","allowDeleteInHeader","itemIsSelectable","angular.isUndefined","kbMultiSelectLinkFn","_selectedItems","_selectedMap","_binding","_isEnabled","_getItemLabel","updateSelected","itemValue","sourceItem","$watchCollection","updateFilteredSource","_itemClick","_itemIsSelectable","isSelected","viewValue","_filteredSource","SearchUtils","_queryChange","_queryKeydown","tab","_itemDeleteBtnClick","ngModelValue","splice","optionVal","trigger","ImageSelectHelper","windowResize","debounce","optionLayout","eOptionLayout","scroll","$items","$firstItem","itemWidth","offsetWidth","itemAndMargin","elWidth","innerWidth","remainder","idealN","idealMargin","wrap","selected","$selected","_selectedItem","_helpClick","selectedElem","nearest","horizontal","nearestEndPadding","parseInt","style","marginRight","indexOf","$templateRequest","$compile","kbInclude","response","$template","angular.element","compiled","replaceWith","promiseTracker","scrollDistance","$child","kbInfiniteScrollParent","findDirectiveElement","kbInfiniteScrollChild","isHorizontal","kbInfiniteScrollOrientation","kbInfiniteScrollDistance","parseFloat","busy","handler","shouldScroll","clientWidth","portalRight","scrollLeft","parentHeight","clientHeight","portalBottom","scrollTop","kbInfiniteScroll","onMousewheel","deltaY","kbInfiniteScrollImmediateCheck","directiveElement","selector","addBack","imageWhenSelected","selectable","onDelete","onDoubleClick","deletable","childTemplate","$templateCache","processTemplateElement","listController","listScope","_listScope","registerListItem","mouseEvent","multiple","ctrlKey","addToSelectedItems","shiftKey","shiftToSelectedItems","setSelectedItems","_itemDoubleClick","selectedItems","skin","_listItems","$id","_selectedListItems","li","_selectedListItem","lastSelectedItem","doNotAutoRemove","newIdx","listItem","updateSelectedItem","undefined","MarkdownDeep","Markdown","OnPrepareImage","tag","src","attributes","parts","md","NewWindowForExternalLinks","v","_html","Transform","ngMax","Infinity","start","ui","floating","tolerance","deleteItem","drawerService","getChildren","dir","param","filter","mscope","apiPath","tracker","startPath","startFile","relativePath","getDirectory","selectedFiles","rootDir","isDialog","isReadOnly","environment","deleteItems","deleteSelectedListItems","refreshList","rename","addFolder","fileDoubleClicked","isFile","navigate","upload","promptUserToChooseFiles","onUpload","promises","uploadFileToMedia","currentDir","uploadProgress","percentComplete","uploadError","all","uploadComplete","crumbClick","crumb","addBlank","ext","addDrawer","addfolder","deleter","startDir","refreshCrumbs","crumbs","segments","segment","content","msg_deletemedia","getListViewSelectedItems","mobject","headers","each","item_1","msg_renamefile","msg_renamefolder","newName","eAlertType","error","newfolder","folderName","getListViewDataItem","$domItem","uploadingFiles","angular.forEach","uploading","uploadDialog","prepend","visible","$sce","thumb","cachebuster","fallback","getFallbackImage","getExtension","extensions","fullPath","video","isAbsoluteUrl","cacheBuster","trustAsResourceUrl","$state","$subMenu","isExpanded","children","collapse_1","unbind","minValidator","ngMin","currency","update","fxConvert","companySettings","toUpperCase","$modelValue","header","dropdown","angular.isFunction","_userInput","_loading","_highlightedItems","newUserInput","lastUserInput","pushArray","getValue","builtItem","_selectMatch","existingItem_1","_selectActive","backspace","pop","up","down","escape","comma","minPrecision","maxPrecision","thousandsSeparator","decimalSeparator","prefix","suffix","step","isNaN","_formattedValue","formatType","Number","$controller","oldTemplate","newTemplate","oldTemplateScope","newTemplateScope","pageDb","updateTemplate","page","pageIden_1","$parentConfigurator","clonedElement","_page","oldPage_1","newPage_1","oldPageIndex_1","getHierarchicalIndex","newPageIndex_1","$oldPageEl_1","$newPageEl_1","isIndexGreater","pageChanged","add","$destroy","indexMap","Page","pages","Configurator","configurators","thisIndex","otherIndex","_getItemValue","_itemKeydown","handles","containment","minWidth","minHeight","maxHeight","onStop","resizeDisabled","exists","destroyResizable","resizable","left","originalPosition","stop","$ripple","$wave","checkbox","kbRippleCheckbox","ripples","rippleHide","delay","performance","now","kbRippleDisabled","initPos","offset","elHeight","offsetHeight","dia","x_1","pageX","y_1","pageY","top","scale_1","class","appendTo","overflow","transform","marginLeft","marginTop","childScope","kbScope","angular.extend","clone","results","customResults","toolbar","scrollParent","colDb","sortBy","binding","sortField","sorted","descending","deepWatch","_selectedLabel","arraySource","readyForValue","updateSelectedLabel","_selectedIndex","MOBILE_WIDTH","isIos","searchBox_1","getElementById","sourceChange","option","labelOrValue","findIndex","optionPlusOne","b","keySearch","className_1","clicked","$document","directEdit","valueVisibility","$thumb","thumbElem","lineElem","valueLineElem","setViewValue","setFormattedValue","getNearestVal","tryVal","floor","setCurrentValue","currentVal","setThumbPos","withAnimation","percent","cssVal","getValFromMousePos","mouseClientX","lineRect","lineWidth","right","cval","rounder","eFormatType","none","number","formattedValue","setTicks","tickPercent","lineClick","clientX","pointerup","dragging","pointermove","$digest","_tracker","kbSpinner","templateElement","kbSrcOnError","svgWidth","svgHeight","svgStyle","kbDragStart","kbDragMove","kbDragEnd","kbClick","defs","maxZoom","minZoom","disablePan","disableZoom","zoomLevel","panX","panY","svg","baseMouse","isDown","dragged","g","svgDims","scale","scrollX","scrollY","svgWidthIsAuto","svgHeightIsAuto","level","updateSvg","x","outerWidth","y","outerHeight","getEvent","modifierX","modifierY","offsetX","offsetY","currentTarget","recalculateSize","thisEl","jQuery","getBBox","bbox","xPos","yPos","render","viewBoxX","viewBoxY","onMousedown","screenX","screenY","onMouseup","inSvg","tagName","onMousemove","sqrt","abs","onWheel","difference","oldZoom","scalechange","location","href","tabsCtrl","_getElement","_tabsScope","registerTab","tabVisibleChanged","selectedTab","tabChanged","tabWidth","customTabWidth","locked","firstRun","_tabs","$container","$headers","$pane","$headersContainer","selectionLineEl","_headerClick","setSelectedTabScope","oldTab","_selectedTabScope","newTab","positionSelectionLine","scrollSelectedIntoView","animateContent","headerEl","offsetLeft","oldTabIndex","newTabIndex","$oldTabEl","$newTabEl","currentHeight","newHeight","updateSelectedTabScope","updatePagination","containerWidth","headersWidth","paneWidth","_paged","_pageNextVisible","_pagePrevVisible","elemLeft","elemRight","setScroll","_scrollNext","_scrollPrev","fixScroll","wheelDelta","mask","_maskConfig","eMaskType","phone","zipCode","placeholderChar","guide","keepCharPositions","showMask","iChildScope","iScopeType","kbTransclude","slotName","kbTranscludeSlot","empty","valid","checked","checkedChanged","labelTemplate","hasChildren","$headerElem","childTemplateProcessed","_children","registerNode","node","_getHeaderElement","_calculateIcon","_icon","_getAncestorNodes","includeThis","ancestorNodes","_parentNode","templateHtml","updateChildTemplate","cloneScope","addChildTemplate","childrenValid","treeController","parentController","thisController","treeScope","_treeScope","updateExpanded","expandable","refreshSelectionLine","select","_selectedNode","_arrowClick","_nodeClick","_checkedChanged","_level","dragDrop","el_1","getDropPosition_1","allow","dropPosition","elementPosition","elementHeight","mouseRelativeToElementY","clientY","ondragstart","_dragNode","dataTransfer","effectAllowed","setData","ondragover","allowDrop","dropEffect","setCurrentDragTarget","ondrop","removeDropClasses","targetParent","sourceParent","dropped","ondragend","ondragleave","animation","selectionStyle","selectionClass","selectionLineColor","_nodes","_currentDragTarget","console","log","updateSelectedNode","scrollToSelectedNode","expandNodeAndChildren","$selectionLine","child","$node","isEqual","nodeEl","bottom","offsetTop","cleared","_fileName","guid","assetId","_thumbnailDataUrl","_btnClick","getAssetUrl","reader_1","FileReader","onloadend","readAsDataURL","messageClicked","hideAutoValidation","autoValidation","_toggleAutoValidation","_getTitle","errors","messageType","eValidationType","warning","noerrors","bytes","precision","isFinite","pow","toFixed","enumName","localize","enumType","locTitle","locDesc","resxName","low","filepath","root","imageName","currencyCode","convertedValue","role","hasRole","toCamelCase","isAdminOrCompanyAdmin","$locale","symbol","currencies","formatted","localSymbol","NUMBER_FORMATS","CURRENCY_SYM","getFullYear","getMonth","getDate","getHours","getMinutes","days","singular","day","week","weeks","month","months","replacements","lkey","localizedString","eLogType","info","mediaPath","eNotificationType","quoteApproved","approve","quoteRejected","NumberFormatFilter","getProfileImageUrl","getFileUrl","String","shadeEnumValue","colorName","shadeNum","backgroundHex","Color","isDark","toHexString","themeService","palette","contrast","getRgbString","getActiveTheme","end","trustAsHtml","eLoginMode","ClaraSceneUtilities","sceneService","sceneApi","ruleType","idMap","nestedSceneId","setProperty","mapId","afterSetProperty","getProperty","setVisible","setVisibleRecursively","frameScene","animateCamera","afterAnimateProperty","animateClip","addModelClickHandler","modelId","addedByRuleType","uniqueId","hotspotId","clearClickHandlers","clickDb","addDraggable","clearDraggables","draggableDb","ghost","clearGhosts","highlight","clearHighlights","clearHighlightsOfType","clearSelection","getId","cache","paths","getName","scene","property","getNode","getQueryObject","getChildNodes","childIds","from","childId","whenAssetsLoaded","sceneIO","whenLoaded","getActiveCamera","player","getCamera","PathCache","_data","getPaths","getIds","getAll","clearEntriesThatContain","searchTerms","keys_1","searchTerms_1","term","forSetAll","JSON","stringify","warn","LastValueCache","valueEqualTo","SceneCache","lastValues","ruleService","_vectorProperties","NESTED_SCENE_PREFIX","convertColorForScene","hex","color","toRgb","normalizePropertyValue","origValue","propertyType","axis","charAt","plug","operator","toggleTool","commands","updateCommand","tool","constrainCamera","radius","constrain","setCameraRadiusConstraint","isClaraId","isGuid","exec","getParentNodeId","nodeId","getChildNodeIds","findAncestorNodeId","parentId","getQueryObjectFromArgs","equalsAny","Logger","logSceneChange","properties","easing","cameraAnimationInProgress","animateCameraTo","toCameraId","queueAnimation","iterations","autoplay","tracks","onEnd","clip","getClips","queueClip","getSceneUtilities","runSceneRules","sceneConfig","uiConfig","ruleArgs","skipRulesIfNoNestedSceneChanges","runNestedSceneRules","r2","importAllUploadFieldImages","sceneUtils","eRuleType","runRuleTypeAsync","ruleResult","$fieldsDirtyForSceneRules","runRulesCycle","runUiRules","sceneDb","idScene","idProduct","clearTransient","preValidate","isValid","nestedConfigs","getNestedConfigurators","promises_1","nested","refConfig","referencedConfigurators","rc","nestScene","$sceneConfigurator","KbObjectManager","configurator","$uiConfigurator","$nestHotspots","nestHotspots","setFields","getFieldsObject","skipRules_1","claraId","publishHash","getNestedSceneRuleArgs","$sceneIdMap","KPromise","$nestedSceneId","company","kom","$manager","parentKom","sceneKom","isRender","isMobile","clientLanguage","logs","ClientLogger","playSceneAnimation","toggleSceneAnimation","sendMessage","selectPage","convertCurrency","obj","getUploadImageNode","importedImages","fieldId","imageNodeId","getTables","nodeWithIdExists","nestSceneInner","fetchScene","fetchedScenes","fetch","waitForPublish","api_1","rootSceneId_1","includeParent","sceneGraph","addNode","plugs","Properties","nullId","nestedObjectsNodeId","nestedMaterialsNodeId","parentMaterialsNodeId","objectsToClone","materialsToClone","allNodesToClone","parentMap","cloneDependencies","nodeMap","onSceneNested","nestedRuleArgs","sceneLoaded","deleteOrphanedNestedScenes","allNested","getAllConfigurators","deleteNode","dumpScene","shallow","checkScene","_store","getIn","uploadFields","getFields","eFieldType","uploadToScene","promises_2","uf","importUploadFieldImage","uploadValue","isNested","nullNodeName_1","imageNodeName","shapeNodeName_1","extrudeNodeName_1","outputName","convertUploadedSceneImageToMesh","targetFormat","threshold","uploadImageThreshold","importObject","prevImportedImage","assets","importImage","svgNodeId","nullNodeId","shapeNodeId","Shape","curveSegments","addOperator","keepAspectRatio","extrudeNodeId","PolyMesh","shape","extrudeLength","snapshot","setCommandOptions","runCommand","getRootSceneId","nodeList","isHierarchicalVisibilityEnabled","rootSceneId","ghoster","selection","addGhoster","selectionSet","highlighter","setHighlighting","thickness","nodeIds","highlights","types","hover","_loop_1","createSelectionSet","setActiveSelectionSet","selectedNodes","deselect","getThree","THREE","SceneViewer","prop","loadDeferred","loadScene","clearHandlers","isStandalone","config","$running","loadSceneInternal","createElem","parentElem","elemSelector","createElement","classList","appendChild","createHotspotElem","hotspotDiv","setAttribute","compileTemplate","resize","notifyLoaded","sendMessageToParent","requestId","runActionRule","actionName","action","actions","runRuleContainerAsync","handleRuleError","$type","setFieldsIfStandalone","messageCallback","refreshElementParent","positionHotspot","pos","hotspot","$top","$left","popupPosition","eHotspotPosition","popupAttach","eHotspotAttach","topLeft","topRight","bottomLeft","bottomRight","popupOffsetX","popupOffsetY","keepPopupInViewer","$popup","popupHeight","popupWidth","popupTop","popupLeft","popupRight","popupBottom","getAllHotspots","allHotspots","allUiConfigs_1","uic","hotspots","HandlerDb","byNode","h","removed","removeWhere","h1","addToDb","handlerId","matchingNode","ClaraSceneRuleArgs","viewer","navigateToElement","allowOrbit","allowPan","allowZoom","ids","tid","tableArraysDb","ClaraViewer","cArgs","hovers","annotationToHotspotDb","prefetchedScenes","_clickAlreadyHandled","hotspotCounter","processingMouseOver","playerUrl","ocLazyLoad","setArgs","hotspotClick","ann","hotspotCloseClick","supportsVr","res","detectWebGL","canvas","WebGLRenderingContext","getContext","init","claraplayer","hideTool","removeTool","displayThumbnail","highlightColor","annotations","useCustomAnnotationFunction","annotationFn","useCustomOverlayFunction","customOverlayFn","addTool","mousedown","loadSceneArgs","clearMemory","clearScene","toggleTools","constrainCameraToRadius","cameraRadius","rulesRun","hierarchicalVisibility","shimThree","runLoadedRule","getRuleArgs","isCommandEnabled","arEnabled","prefetchScenes","fetchAndUse","activateCommand","loadedRuleResult","runRules","hit","currentFilterNodes","filterNodesFromPosition","activeDrag_1","activeNodeId_1","nid","dragStarted_1","dragNode_1","$activeNode","three_1","startPos_1","Vector3","setFromMatrixPosition","getWorldTransform","displayGizmo","plane","eDragMode","normal","constant","distanceFromOrigin","surfaceNodeIds","surface","surfaceNodes","keepOffset","shouldMove","newPos","hitData","uv","dragNode","startPos","relativeSurfacePos","dragStart","activeDrag","clearAnnotations","clickArgs_1","clickedNode","propogate","clickArgs_2","clickdb","dragdb","clearMouseOver","hoverParentId","setMouseOverEffectRecursive","handlers","arg","$hover","three","$originalUpdateMatrixWorld","Object3D","updateMatrixWorld","force","updateMatrix","createdCache","_positionCache","_quaternionCache","Quaternion","_scaleCache","_visibleCache","equals","quaternion","matrix","compose","matrixWorldNeedsUpdate","copy","prefetch","resolveHotspotTargetNode","targetNode","div","hotspotProcessed","_loop_2","resolvedTargetNode","this_1","getScreenPosition","targetShape","eHotspotShape","mesh","$uid","annotation","alpha","$zindex","idCamera","animationDuration","animationEasing","nestedNullId","clickArgs_3","allowClose","animateArgs","nestedConfig","nestedSceneClickToSelect","cursor","findAncestorNode","parentNode","runAction","runFieldAction","waitForLoad","dispose","ConfiguratorHelper","filterLevelDb","_optionFilterRunCount","downloadTables","tableIds","tables","getBatch","loadTables","itables","table","Table","toObjectArray","ruleName","hasError","showErrors","dialogScope","configuratorName","parameters","message","persist","ruleContainer","runRuleContainerSync","runActionByIdAsync","actionId","runActionRuleByIdAsync","runOptionFilterSourceRule","autoCompleteQuery","autoCompleteSource","eAutoCompleteSource","arr","idTable","scrubName","labelColumn","valueColumn","scrubValueCol_1","scrubLabelCol_1","scrubImageCol_1","imageColumn","Option","database","products","autocomplete","autoCompleteGetLabel","scrubValueCol_2","scrubLabelCol","row","getOptionFilterSource","eOptionFilterSource","tableObject","optionFilter","idOptionFilter","$source","shouldRunOptionFilter","shouldRun","optimized","last_1","$lastValues","isArrayType","queryMode","eQueryMode","$shouldRun","parentOptionFilter","runOptionFilter","filterId","source_1","clientLang","shouldTranslate","defaultLanguage","matchedRows","scrubDescTranslateCol","fieldIds","fieldBaseType","getBaseType","fieldIsArray","newOptions","scrubValueCol","scrubSortCol","sortColumn","scrubTranslateCol","scrubImageCol","scrubImageWhenSelectedCol","imageWhenSelectedColumn","scrubDescCol","descriptionColumn","uniqueDb","matchedRows_1","rowIndex","entry","Field","convertToType","sort","sortCol","eSort","ascending","sortByDescending","handleSingleOption","cellValue","storeLastValuesFor","singleOptionBehavior","eSingleOptionBehavior","disable","last_2","fieldReferences","runSelects","optionFilters","$freezeFieldValueCalculation","startTime","odb","allFields_1","canJoinOptionFilter","selectSource","eSelectSource","filtersShouldRunOnClient","filterIds","fieldOptions_1","lastValues_1","runArgs","configuredProduct","getConfiguredProduct","fieldOptions","run","filters","filterResult","fields","logRuleEnd","SCENE_CLICK_HANDLER_TAG","Kb3dViewer","enableScreenshots","arActive","ar","xrActive","toggleAr","kb3d.KbViewer","container","KbColor","FromIntObject","webworkerPath","clusterEnv","assetRoot","debugMode","forceDisableGraphicsOptimization","detail","arEnabled_1","viewChanged","subscribe","updateHotspots","interaction","onKeyboard","gizmos","clearGizmo","sceneNode","_manager","clickHandlers","deleteByTag","manager","kb3d.Kb3dManager","forceFullSizeTextures","isRenderContext","lastDeploy","deserialize","graph","fullscreenEnabled","$sceneNode","_configurator","loadingExperience","kb3d.eLoadingExperience","deferLoadingPromise","configuratorLoadedPromise","onSceneClick","clearTransientHandlers","ruleTypes","handlerMaps","doubleClickHandlers","draggables","hotspotClickHandlers","handlerMaps_1","hm","nestedSceneRulesWereRun","$ranLoadedRule","skipRules","alwaysChild","alwaysChildOf","parentSceneNode","ser","nestedSceneNode","scenes","ns","destroyNestedScene","parentScene","nestedScene","runSceneFunction","function","functions","clearHotspots","startRender","stopRender","viewpoint","take","rulesFn","rt","arLoading","active","xrExit","xrEnter","subscription_1","onSessionEnd","unsubscribe","overlayElem","arPromise","catch","err","addPromise","digest","sceneManager","getById","camera","getScreenBoundingBoxOfNode","eventTag","has","hSceneNode","getByKey","animateToViewpoint","handlers_1","propagate","Kb3dSceneFunctionRuleArgs","Kb3dSceneRuleArgs","renderPass","kbv","getByName","getFirstNodeByName","getIdByName","getNodeByIdOrName","getParent","_parent","getNestedPathTo","getNestedPathInConfigurator","configs","lastItem","lastConfig","kb3dNode","setParent","opts","newParentNode","newParent","preservePosition","isSpaceNode","getTransformSpaceDifference","isAnnotation","deleteByKey","removeChildren","forceAndWaitForNextRender","setRotationQuaternion","rotationQuaternion","scaling","translation","addChildren","calculateParents","_e","nodes","getNestedSceneNode","kb3d.Kb3dObject","activeCamera","getNodesByIdOrName","feature","selectMany","MaterialNode","getTextureByName","SpaceNode","getFeatureByName","nodes_1","subProp","kb3d.Token","propType","isPrimitive","normalizePropValue","convertColor","eColorFormat","kbcolor","__assign","nestedNameOrInstance","toFormat","kb3d.KbColor","toIntObject","hsl","toHsl","hslString","toHslString","hsv","toHsv","hsvString","toHsvString","rgb","rgbString","toRgbString","colorOperation","operation","amount","addClickHandler","digestEvent","getHandlerTag","addDoubleClickHandler","addHotspotClickHandler","addBoundboxChangeHandler","boundingboxChangeHandlers","argsTag","handlerMap","handlerType","kb3d.eHandler","doubleClick","draggable","nodes_2","toValue","queue","Promise","frameCamera","addToParent","createSketchPath","SketchPath","controlPoints","kb3d.SketchControlPoint","getChildrenOfType","tok","filterByType","searchByName","nodes_3","kb3d.SpaceNode","clearAll","activateGizmo","attachMesh","gizmo","overrideSpaceNode","updates","rotate","axisVisibility","startQ_1","KbQuaternion","FromRotationAxis","rotationAxis","rotationAngle","startEuler_1","eulerRotation","_primeMover","qGizmo","FromYawPitchRoll","rotation","bnode","getRendererNode","inSpace","computeWorldMatrix","applyTransformToSpace","worldTransformMatrix","useEuler","toEuler","multiply","getAngle","getAxis","q","z","totalDelta","getRotationQuaternion","toQuat","newPosition","clearGizmos","activateSketchEditor","clearSketchEditor","kb3d.SketchNode","sketchEditor","startOnPlane","intersect","snapSize","modified","mouseUp","overwriteSketchWithSVG","svgImage","resp","blob","applySvgToSketch","getAbsolutePosition","kb3d.KbVector","From","Zero","getSketchPathLength","pointsArray","_points","point","prevPoint","hypot","computeLength","getBoundingBox","space","bbCache","getWorld","refreshAndGet","nodesIntersect","node1","node2","copyPropertiesTo","fromNode","toNode","copyingToDifferentNode","getMateChain","activeMates","getActiveMates","kb3d.getNodeChain","angle","callSceneFunction","returnValue","waitForNextRender","convertAxisAngleToEuler","kb3d.KbQuaternion","getGlobalMaterialNode","rendererManager","material","loadGlobalMaterial","services","childToken","ev","$injector","request","method","extension","env","eEnvironment","dev","test","lastTestDeployment","lastProdDeployment","responseError","ignoreErrors","angular.toJson","ForbiddenReason","SsoNoGroups","InsufficientPermissions","securityRetryQueue","isSfdcCpq","ignoreSecurity","$http_1","doNotReplay","pushRetryFn","loginRequested","permissionDenied","$location","adminProducts","AdminProductClient","automationStudio","AutomationStudioClient","builders","CrudClient","buildTypes","builderSettings","SingletonCrudClient","categories","CategoriesClient","changePassword","channels","companies","ConfiguratorClient","contacts","CurrencyClient","customActions","customers","dashboard","dbTables","DbTablesClient","deployments","DeploymentClient","emailTemplates","generators","GeneratorClient","globalDefinitions","integrationSettings","IntegrationSettingsClient","jobs","JobsClient","kinetic","KineticClient","languages","LanguageClient","layouts","LayoutClient","notifications","NotificationClient","notificationSettings","OptionFilterClient","outputBuilders","permissions","PermissionClient","priceColumns","PriceColumnClient","ProductClient","productHistory","ProductHistoryClient","productRules","queues","quoteHeaders","QuoteHeaderClient","quoteOutputs","quotes","QuoteClient","quoteProducts","roles","safeFunctions","SafeFunctionClient","savedSearches","SavedSearchClient","ScenesClient","sceneHistory","SceneHistoryClient","settings","CompanySettingsClient","TablesClient","tags","testBuilds","TestBuildClient","themes","tools","ToolsClient","translate","TranslateClient","UserClient","workflows","WorkflowsClient","workflowSelectors","dbWhitelist","DbWhitelistClient","dbXuserCreds","DbXuserCred","interactions","kineticMom","KineticMomClient","cookieToken","defaults","common","getProxyClient","entityTypeName","admin","service","getFromEnvironment","waitForRefresh","insert","upsert","getPaged","items","searchPaged","fullArgs","skip","suggest","uniqueValues","rebuildIndex","getToken","translateArray","deploy","compare","save","runIndexOperation","rebuildIndexAllEnv","rebuildIndexAll","rebuildRootIndex","recreateStorage","pullFromProduction","update3DPlugin","recreate3D","recreateDns","cleanDb","pullSfdcProducts","soqlStatement","whereClause","getSearchableTypeNames","getPriceColumnsForUser","reorder","getDocumentRulesSchema","idConfig","getDocumentRulesSchemaForDynamicAttributes","testConnection","getLogs","idJob","updateFromSource","states","externalValues","kb3dEnabled","classic3dEnabled","values","convertToKb3d","getSceneHistory","getHistoryByIdHistory","idHistory","cloneHistoryToNewScene","idSceneHistory","revertSceneToHistory","tree","getAllSizeInfo","checkSfdcCredentials","checkOracleCpqCredentials","getSsoGroups","keywords","getSsoGroupById","groupId","companyOptions","companyCurrencies","getExchangeRates","baseCurrency","supportedLanguages","next","deleteAndAnonymize","resetPassword","acceptPrivacyPolicy","resetDeactivation","selections","baseurl","idConfigurator","meta","Product","isConfigured","searchFields","getIsConfiguredFilter","getOutput","idOutput","getProductHistory","cloneHistoryToNewProduct","idProductHistory","revertProductToHistory","isTest","fast","productId","searchByCategory","uniqueAttributeValues","attributeRanges","quote","getProductBuildTypes","idQuote","copyQuoteProduct","idQuoteProduct","getQuoteProduct","insertQuoteProduct","quoteProduct","editQuoteProduct","buildQuoteProduct","idBuildType","deleteQuoteProduct","runQuoteHeaderRule","mySearches","getQueue","buildId","updateSfdcCredential","apiUsername","apiPassword","apiToken","sfdcApiUsername","sfdcApiPassword","sfdcApiToken","editCurrencySetting","currencySetting","getDefault","signalrService","userDeferred","userPromise","contextDeferred","contextPromise","loadContext","serverVm","fx","base","rates","cc","rate","kbmaxLogoPath","channel","companyLogoPath","logoPath","confirmLogin","login","email","password","rememberMe","loginError","logout","loginTracker","reload","go","retryAll","loginSuccessful","keepAlive","isInRole","userHasRole","bret","isAdmin","ANONYMOUS_USER_ID","keyStr","encode","chr1","chr2","chr3","enc1","enc2","enc3","enc4","output","charCodeAt","decode","fromCharCode","$ocLazyLoad","_libs","getBundleUrl","serie","recaptchaToken","minifyIfNotDebug","eClusterEnv","debug","paralell","urls","lib","$stateParams","$transitions","$sanitize","alerts","dialogs","progress","confirmMessage","yesCallback","noCallback","timeShown","inProgress","reason","showPromiseReasonOnFail","closeAlert","defaultOptions","buttonArgs","DialogButtonArgs","angular.isString","kbDialog","keypress","fullHeight","button","close","dialogOptions","InputDialogButtonArgs","eMediaFilter","imagesAndVideos","images","videos","environments","dStartPath","MediaDialogButtonArgs","dSelected","drawers","showHelp","onEnter","transition","pageTitle","pageIcon","pageType","setHelpUrl","command","drawer","disabled","record","localStorage","userGuid","fly","sourceSelector","targetSelector","eq","$fly_1","effect","times","getEnumSelects","enm","selects","name_1","locName","locValue","copyDataToClipboard","$el","$textarea","textarea","setSelectionRange","pasteClipboardData","fxConvertAsync","deferred","$cookieStore","quoteIdFromCookie","getActiveQuoteData","guidToken","ownedBy","allowedActions","eWorkflowAction","modifyProducts","QuoteService_1","COOKIE_NAME","_quote","storeCookie","configurable","cookie","parse","getLatestQuoteProduct","addProduct","idWorkflow","confirm_1","silent","newQuoteProduct_1","qty","contentTracker","existingProduct","qp","addLocally","getNewQuote","canModifyProductsOfQuote","copyProductToActiveQuote","copyProductToNewQuote","goToQuote","newquote","discountPercentage","getQuoteById","_masterRuleCache","getConfiguratorHash","idQuoteHeader","getRuleName","getRuleHeader","toSentence","stars","repeat","getConfiguratorMasterRule","hash","globalRc","ruleContainers","global","js_1","js","globalEventRc","globalEvent","ruleContainers_1","CToken","Button","SvgViewer","NestedSet","RuleContainer","ruleJs","Function","compileAsyncRule","runRuleAsync","runJsAsync","compileSyncRule","runRuleSync","runJsSync","masterRule","start_1","logRuleStart","writeRuleCycleLogs","base64Service","retryQueue","shift","retry","retryFn","deferredRetry","retryItem","onItemAdded","dynamicOptionsToQueryStatic","isSfdc","canvasRequest","sfdcCanvasRequest","navigateToObject","Sfdc","client","publish","payload","toggleFullscreen","makePrimaryQuote","sr","links","restUrl","externalId","ajax","contentType","KBMAX__Primary__c","getPayloadFromSfdcCpq","onData","getProducts","productCodes","getColumnOrMetaValue","priceItem","colNames_1","colName","metadata","metaNames_1","metaName","getConfigurationAttribute","att","product","configurationAttributes","addColumnsAndMetadataToConfigurationObject","configurationData","col","buildOptions","optionConfig","isDynamic","salesforceId","dynamicOption","ProductCode","sku","Quantity","dynOptsBuild","optionConfigurations","ProductName","optionId","dynOptionsToQuery","clearNestedOptions","saveToSfdcCpq","priceObject","foundInOptions","featureLoop","options_1","dynamicFeature","attValue","dynamicOptionsQueryPromise","removeNulls","dynOption","product2","Id","SignalrService","stopping","crudConnection","notificationConnection","HubConnectionBuilder","withUrl","serverTimeoutInMilliseconds","withHubProtocol","JsonHubProtocol","configureLogging","LogLevel","Information","build","crudConnectionPromise","notificationConnectionPromise","notificationOn","notificationOff","notificationInvoke","methodName","invoke","publicStorageUrl","appInsightsKey","snippet","instrumentationKey","disableAjaxTracking","Microsoft","ApplicationInsights","_appInsights","loadAppInsights","onSuccess","lastState","protocol","host","trackPageView","setDefaultProperties","subdomain","Company","App","trackEvent","trackException","exception","defaultThemes","eSkin","background","primary","accent","border","dark","font","fontSize","classic","loadTemplate","parseAndLoad","onFinish","themeCss","getDefaultTheme","queryString","idTheme","theme","sfTheme","current","shade","grayscale","darken","getOriginalInput","lighten","setAlpha","parseTheme","hueRegex","RegExp","cType","opacityNum","replaceAll","customFontUrl","setThemeToHead","innerHTML","head","refreshActiveTheme","currentTheme","uploadInputHelper","currentCallback","removeAttr","entity","postConfig","transformRequest","angular.identity","formData","FormData","uploadResult","xhr","XMLHttpRequest","onreadystatechange","readyState","onprogress","send","filename","importConfigurator","uploadFile","uploadConfiguredProductFile","convertPdfToImage","uploadQuoteFile","BaseController","uiOnParamsChanged","changedParams","$transition$","CrudController","agg","loadPromises","deleteMsg","onSocketRelationshipEdited","editedId","relationshipName","relationshipEditedCallbacks","onSocketDeletedDelegate","onSocketDeleted","onSocketEditedDelegate","onSocketEdited","markChangesClean","offTransition","onStart","bypassUnsavedConfirmation","modelIsClean","d_1","msg_confirmunsavedchanges","onbeforeunload","offOnLogin","isEdit","isNew","isView","onCancel","history","back","handleResponse","responseData","responseStatus","getValidationObject","alertMsg","form","msg_formerror","msg_500error","webSocketEntityType","savePut","savePost","isSaving","getModelForSave","setUpdatedModel","angular.equals","cleanModel","angular.copy","newProp","sections_1","section","entityType","uniqueName","onRelationshipEdited","ContactController","crudService","msg_deleterecord","contact_title","idCompany","shipToBillingAddress","canModifyCustomers","SearchController","bypassInit","pageSize","epoch","filledFilterSources","savedSearchEnabled","allowSearch","getExtraFilters","eFilterControl","dateRange","eFilterType","postProcessFilters","sortInfo","getSortInfo","nestedPath","getNestedPath","nestedFields","infiniteScrollTracker","searchCall","massageResults","suggestValueField","addFilter","newFilter","fillFilters","removeFilter","multiSelect","toggleFilters","lastLength","lastRetrieved","modelTypeChange","infiniteScroll","count","getQueryStringParams","basicSearch","filterSource","eFilterSource","filterSourceInfo","manufacturers","enum","editSearch","saveSearchDialog","deleteSearch","canDeleteSearch","isCompanyAdmin","loadedFromQueryString","newSearch","availableFilters","getFiltersFromMeta","refreshSavedSearches","getFieldsFromMeta","attribute","productsScope","attributeDb","attributeId","eAttributeType","useRangeBuckets","ret","sortFilter","sourceType","productSorts","eProductSortBy","relevance","popularity","priceLowToHigh","priceHighToLow","nameAtoZ","info_1","sf","onlyDefaults","every","toPascalCase","$name","headerField","sticky","getFilterKey","selectedCategory","unsubmitted","capitalize","any","manufacturer","suggestQuotes","suggestContacts","suggestCustomers","suggestProducts","eproductsortby_relevance_title","eproductsortby_pricelowtohigh_title","eproductsortby_pricehightolow_title","eproductsortby_popularity_title","eproductsortby_nameatoz_title","categoryIds","getChildCategories","att_1","ranges","buckets","vals","confineToList","vals_1","headerFields","fillSorts","onItemsDeleted","dscope","ss","sortColumnName","ContactsController","Contact","CustomerController","customer_title","customer_type_direct","customerTypes","CustomersController","fixUrl","Customer","DialogController","NotificationsController","Notification","DrawerController","resizeDrawer","totalWidth","$drawerButtons","LoginController","loginModel","userModel","forgotPasswordModel","registrationModel","ssoEnabled","loginVisible","setMode","ssoSignIn","isDefined","embedded","showAltLogin","altLogin","off1","getParameterByName","off2","agreedToPrivacyPolicy","thanks","submitForgotPassword","forgotPasswordSubmitted","allowAnonymousLogins","prod","PortalController","quoteService","sfdcService","pendingApprovals","opp","showMobileMenu","mobileMenuVisible","hideMobileMenu","refreshNotifications","onNotificationSignal","companySubdomains","browseToSubdomain","browseToEnvironment","envSuffix","focusin","phase","$$phase","mobileKeyboard","focusout","readNotification","notification","read","urlPath","markAllNotificationsAsRead","newNotificationCount","snapStudioMode","hideHeader","PrivacyPolicyController","privacyPolicyModel","agree","agreed","u","hasLatestPrivacyPolicy","canPromise","toSJISFunction","CODEWORDS_COUNT","utils","version","digit","kanji","createCommonjsModule","basedir","module","commonjsRequire","errorCorrectionLevel","L","bit","M","H","string","fromString","BitBuffer","buffer","bufIndex","num","putBit","getLengthInBits","bitBuffer","BitMatrix","size","Uint8Array","reservedBit","reserved","xor","isReserved","bitMatrix","alignmentPattern","getSymbolSize","require$$0","getRowColCoords","posCount","intervals","ceil","positions","reverse","getPositions","coords","posLength","j","finderPattern","maskPattern","Patterns","PATTERN000","PATTERN001","PATTERN010","PATTERN011","PATTERN100","PATTERN101","PATTERN110","PATTERN111","PenaltyScores","getMaskAt","getPenaltyN1","points","sameCountCol","sameCountRow","lastCol","lastRow","getPenaltyN2","getPenaltyN3","bitsCol","bitsRow","getPenaltyN4","darkCount","modulesCount","applyMask","pattern","getBestMask","setupFormatFunc","numPatterns","bestPattern","lowerPenalty","penalty","EC_BLOCKS_TABLE","EC_CODEWORDS_TABLE","errorCorrectionCode","ECLevel","EXP_TABLE","LOG_TABLE","galoisField","polynomial","mul","p1","p2","coeff","GF","mod","divident","divisor","generateECPolynomial","degree","poly","ReedSolomonEncoder","genPoly","initialize","Polynomial","paddedData","buff","reedSolomonEncoder","versionCheck","numeric","byte","KANJI","BYTE_KANJI","BYTE","NUMERIC","ALPHANUMERIC","TEST_KANJI","TEST_NUMERIC","TEST_ALPHANUMERIC","regex","testKanji","str","testNumeric","testAlphanumeric","ccBits","MIXED","getCharCountIndicator","VersionCheck","getBestModeForData","dataStr","Regex","G18_BCH","getReservedBitsCount","Mode","getTotalBitsFromDataArray","totalBits","reservedBits","getBitsLength","getCapacity","dataTotalCodewordsBits","ECCode","usableBits","getBestVersionForData","seg","ecl","currentVersion","getBestVersionForMixedData","getBestVersionForDataLength","getLength","getEncodedBits","G15_BCH","formatInfo","NumericData","write","group","remainingNum","numericData","ALPHA_NUM_CHARS","AlphanumericData","alphanumericData","ByteData","second","encodeUtf8","byteData","KanjiData","kanjiData","dijkstra_1","dijkstra","single_source_shortest_paths","predecessors","costs","cost_of_s_to_u","adjacent_nodes","cost_of_s_to_u_plus_cost_of_e","cost_of_s_to_v","PriorityQueue","make","cost","extract_shortest_path_from_predecessor_list","find_path","T","sorter","default_sorter","getStringByteLength","unescape","encodeURIComponent","getSegments","getSegmentsFromString","numSegs","alphaNumSegs","byteSegs","kanjiSegs","s1","s2","getSegmentBitsLength","buildSingleSegment","modesHint","bestMode","fromArray","array","acc","segs","buildNodes","prevNodeIds","nodeGroup","currentNodeIds","lastCount","prevNodeId","buildGraph","optimizedSegs","curr","prevSeg","mergeSegments","rawSplit","setupFormatInfo","bits","FormatInfo","createData","remainingByte","totalCodewords","ecTotalCodewords","dataTotalCodewords","ecTotalBlocks","blocksInGroup1","totalCodewordsInGroup1","dataCodewordsInGroup1","dataCodewordsInGroup2","ecCount","rs","dcData","ecData","maxDataSize","dataSize","createCodewords","createSymbol","Segments","estimatedVersion","rawSegments","Version","bestVersion","dataBits","moduleCount","modules","FinderPattern","setupFinderPattern","setupTimingPattern","AlignmentPattern","setupAlignmentPattern","setupVersionInfo","inc","bitIndex","byteIndex","setupData","MaskPattern","qrcode","toSJISFunc","utils$1","hex2rgba","hexCode","hexValue","getOptions","margin","light","rendererOpts","getScale","qrSize","getImageWidth","qrToImageData","imgData","qr","symbolSize","scaledMargin","posDst","pxColor","qrData","canvasEl","getCanvasElement","ctx","createImageData","clearRect","clearCanvas","putImageData","renderToDataURL","toDataURL","quality","getColorAttrib","attrib","svgCmd","cmd","svgTag","cb","qrcodesize","bg","moveBy","newRow","lineLength","qrToPath","viewBox","renderCanvas","renderFunc","argsNum","isLastArgCb","QRCode","eUserActivationMode","browser","toCanvas","CanvasRenderer","_","SvgRenderer","SelectedBinding","PropertyChangedEvent","setPage","newPage","oldPage","changed","_node","newNode","firstPage","parentConfig","isSingleNode","ConfiguratorRuleArgs","activeUrl","windowWidth","windowHeight","helper","callSafeFunction","safeFunctionId","startIntervalFunction","timeSeconds","runContinuousAsyncRule","stopIntervalFunction","cancelScheduledRule","startTimeoutFunction","func","runTimeoutRule","generateNumber","generatorId","selectNode","nextPage","backPage","runSceneAction","sv","activeSceneViewer","setScene","runNamingRule","naming","addNestedConfigurator","idParent","addNestedConfig","copyNestedConfigurator","sourceConfig","copyNestedConfig","setNumberOfNestedConfigurators","setNumberOfNestedConfigs","removeNestedConfigurator","removeNestedConfig","showPriceDetails","showPricing","fromConfigurator","setLayoutSetting","layoutConfig","getByIdOrName","$layoutSettingsDirty","getLayoutSetting","runConfiguredProduct","configProd","SvgRuleArgs","ConfiguratorController","$interval","telemetryService","interactionService","runAsyncRule","productDb","translationDb","sceneViewerDb","loading","runningRules","configuratorLoadedDeferred","layoutLoaded","isScene","pricingTracker","priceDialogTracker","showSpinnerPricing","showMove","showmove","isEmbed","embedFields","embedLayoutSettings","embedParameters","embedCurrency","deferLoadedRule","isKinetic","actionsVisible","absUrl","hideDrawer","showdrawer","transparentBackground","transparentbackground","showheader","requestid","translateKbo","configDb","getConfigurator","rootConfig","pageParentConfig","pageChangedArgs","selectedPage","includes","enterArModal","trackConfigPageView","queueRule","parent_1","$expanded","getRuleJs","runRuleCycleUnit","oncePerCycleRule","getCurrentConfigForViewerAndSetViewerMode","runLayoutRule","refreshViewer","calculateNodes","testBuild","runSubmitRule","buildRuleArgs","owner","shortDescription","queueId","testBuildName","idQueue","cloudBuild","beforeBuild","getSubmitButtonText","submitButtonText","addtoquote","getSubmitAndStayButtonText","submitAndStayButtonText","saveandstay","getGenerateQrCodeText","generateQrCodeText","generateqrcode","submitButtonClick","getTargetElementId","elementId","getSvgArgs","svgViewer","$originalStartEvent","mouseX","mouseY","commitDrag","originMouseX","originMouseY","originElementId","runSvgAction","queueEventRule","originalDragStartEvent","svgViewerShouldEnablePanAfterDrag","svgDragStart","svgDragMove","dragMove","svgDragEnd","dragEnd","fieldValueChange","fieldTouched","hasBeenTouched","validationTiming","eValidationTiming","onTouched","tabControl","queueEventRuleType","keydown","HTMLInputElement","HTMLTextAreaElement","HTMLElement","keyArgs","altKey","metaKey","expanderChanged","nestedTabSelected","nestedName","nestedSet","nestedSetSelected","togglePages","showPages","resizeScene","refreshDrawer","pageClick","nextNode","backNode","nestedClick","thisCtrl","uploadOptions","convertUploadPdfToImage","uuid","$fieldsDirty","external","sceneUploadPromise","uploadCleared","getCurrency","parentQuote","sfdcHasCurrency","sfdcCurrency","lastPricingPromise","itemsInView","addLevelsToPricing","flat","getColumnValue","systemColumn","useRollup","discountType","totalDiscount","percentage","eColumnType","formatMinPrecision","formatDecimalSeparator","formatThousandsSeparator","formatPrefix","formatSuffix","openItem","nestedItem","smartColorStyle","totalCount","currCount","addNestedConfigClick","entries","userCanAddToDb","idNested","addedByUser","nestedRunBottomsUp","togglePageSlide","pageSlideVisible","messageHandler","data_1","messageName","correspondenceId","response_1","readyToStart","runPricing","messageArgs","hasRule","runResizeRule","layout","args_1","hasPricing","priceColumnDb","pc","pricePrecision","builds","drawers_1","gear","testbuild","testpricing","pricingArgs","quoteCreator","quoteOwner","pricing","runnamingrule","drawerSubmitAndStay","drawerSubmit","buildType","drawers_2","setAllNestedSetElements","startConfigurator","ConfiguratorController_1","animateTo","waitFor","waitPromise","ancestorNestedSets","findAncestor","kbo","eNestedSetDisplay","$uiObject","$domId","handleNewConfigInNestedSet","showSubmitButton","loadSfdcCpqPayload","sfdcCpqPayload","quoteProductId","CurrencyIsoCode","loadModel","getProductId","addTranslationsForEntity","trans","translations","objects","configuratorPromise","session","configSession","loadLayout","fillSourcedTables","userCanAddTo","pageId","showMoveAnimation","LayoutConfig","layoutSettings","ls","lsname","getLoadedRuleArgs","origNumberOfNesteds","saveToQuote","Name","setSubmitButtonDisabled","stayOnPage","validationPromptDisplayed","shouldSubmit","should","qrCodeModal","autoStartAr","updateQrCode","QrCode","pushState","panel","HTMLCanvasElement","drawImage","enterArButton","allowSaveWithErrors","msg_savetoquoteerrors","keepworking","msg_fixerrorsbeforesave","addKbObject","getConfiguratorUniqueKey","runNestedRuleType","configuratorAdded","looping","nestedSettings","configuratorCopied","navigateTo","$nestedSetElement","autoNavigateToElement","removeKbObject","configuratorRemoved","configsChanged","prom","parentConfig_1","getChildrenForNode","tabNode","rootNode","getNextNode","getBackNode","skipChildren","parent_2","prev","parent_3","previous","ruleAction","activeRule","bubble","cycleLimit","nestedRulesRan","configWasDirty","dirtyArr","bubbleRules","runValidationRule","visibility","origNumberOfNesteds_1","nesteds","references","nestedRunTopDown","continueRun","getParameters","changedField","viewerMode","isCrm","createSceneViewer","sceneViewer","viewerScope","vArgs","bare","claraV2LibraryUrl","lastViewerPromise","currentConfig","eViewerMode","viewerDeferred","origSceneViewer","origConfig","viewerMediaPath","clearMemoryWhenSwitchingScenes","isViewerInLayout","waitForViewerReady","elemDefer_1","Q.defer","waitedFor_1","check_1","hasPricingRule","hasNestedPricing","$level","nestPriceObject","parent_4","pageName","sfdcQuote","fullQuote","sfdcConfiguredProductId","configuredProductId","sfdcQuoteLine","scheduledRules","interval","showSpinner","runningRule","sourcedTableIds","sourcedTables","ProductCompareController","productcomparison","cast","addToQuote","minQty","removeProduct","comparedProducts","ProductController","standardProducts","selectedMedia","selectMedia","getVolumeDiscountText","volumeDiscount","nextTier","orderedVolumeDiscounts","volumeDiscounts","units","andabove","relatedProductsQuery","relatedProducts","msg_productcomparisonlimit","ProductsController","flatCategories","flatten","imagemode","imageMode","displayProductsInImageModeByDefault","setToImageMode","setToListMode","cat","translateSuggestion","languageIso","selectedCategoryId","refreshAttributeFilters","addProductPromise","loadSelectedCategory","preInit","$addQty","getCategory","expandToSelectedCategory","sortby","cats","cats_1","addParentRef","selectedAncestors","availableAtts","getSelectedCategoryAttributes","fieldName","attFilters","fieldType","availableAtts_1","parentCats","selectedCat","lft","rgt","onlyActiveCategories","ConfiguredProductsController","configuredproducts","QuoteProduct","modelTypes","Quote","massageFilters","getWhereFieldFilter","fieldsDb","fieldChange","numberRange","boolean","showCopyToActiveQuoteBtn","showCopyToNewQuoteBtn","useDatabaseSearch","price","modifiedDate","customer","idCustomer","contact","idContact","totalPrice","createdDate","fieldValue","QuoteHeaderRuleArgs","selectedPageId","cp","QuoteController","quote_title","validationMessages","productsInView","productBuildTypes","setUpdatedModelInternal","idcategory","updateName","validate","allowInvalidQuotesInWorkflow","executeAction","modifyName","promptUserToFixErrors","revertToClean","updateCurrency","modifyCurrency","updateCustomer","modifyCustomer","updateDiscount","modifyDiscount","updateShipping","modifyShipping","updateProduct","requiresUpdate","updateProductDescription","modifyQuoteProductDescription","getAvailableProductBuildTypes","availableProductBuildTypes","buildProduct","handleActionResponse","quoteproductbuilding","commentListApi","downloadQuoteProductFile","expandedProducts","toggleExpansion","downloadAttachment","hasFileGenerating","generating","deleteProduct","msg_deletequoteproduct","isActiveQuote","showCopyToThisQuoteBtn","canModifyProducts","copyProductToThisQuote","copyProduct","extNet","discount","vd1","vd2","vd","disc","minus","fixedPrice","plus","extCost","fixedCost","sum","mapFn","previousValue","currentValue","propValue","totalCost","totalExtNet","shipping","showFixedPrice","openGoalPriceDialog","undiscountedValue","panes","inSteelbrick","searchProducts","Q.resolve","submitQuickAdd","quickAddQuery","productSortableOptions","canReorderProducts","reorderProducts","handle","actionType","modifiedProduct","idCustomAction","getDataDeferred","headerValues","defConfig","custom","dialogScope_1","other","notes","reasons","rejectedReasons","continuer","modifyQuoteHeader","getCurrencyName","iso","validationMessageClicked","refreshPermissions","refreshDrawers","setupQuoteHeader","stopValidationTimer","enableCustomersAndContacts","canViewCustomer","canModifyCustomer","startValidationTimer","canvasParams","autoSubmit","productImageChange","refreshComments","visiblePages","hasBuildProductAction_1","addAttachments","modifyAttachments","completeBuild","failBuild","addproduct","pbt","idBuildTypes","drSubmit_1","play","endGroup","drPrimary","KBMAX__Opportunity__c","startGroup","drDone","canUserPerformAction","canModifyName","canModifyDiscount","canModifyQuoteHeader","canModifyAttachments","canModifyCurrency","canModifyShipping","canViewQuoteHeader","userViewPermissions","permission","eViewPermission","viewQuoteHeader","canViewDiscount","viewDiscount","canViewCost","viewCost","canViewPricing","viewPricing","viewCustomer","canViewCurrency","viewCurrency","canViewShipping","viewShipping","canModifyQuoteProductDescription","canViewQuoteProductDetails","viewQuoteProductDetails","canSetQuoteCustomer","canSetQuoteDiscount","canSetQuoteShipping","canSetQuoteCurrency","canViewQuoteDiscount","canViewPrices","canViewQuoteCustomer","canViewQuoteCurrency","canViewQuoteShipping","canSetQuoteProductDescription","propertyName","object","productError","includeInValidationMessages","getErrors","hasErrors","allowFractionalQty","maxDiscount","maxDiscountPercentage","maxQty","hasQuoteRule","_stopValidationTimer","QuotesController","openProduct","getFirstProductImage","enableQuoteImport","import","items_1","headerValue","ChangePasswordController","UserActivationController","pass","activationGuid","confirmPassword","encodePassword","goToLogin","UserController","isReadOnlySso","ssoManualUserManagement","isSsoUser","notificationSetting","isApproved","licenseType","eUserLicenseType","internal","ur","msg_resetdeactivationcomplete","msg_passwordreset","msg_deleteuser","canEdit","canResetPassword","canChangePassword","canModifyUsers","notificationOptions","eNotificationSetting","pendingApprovalNotificationOptions","enotificationsetting_email_title","enotificationsetting_none_title","enotificationsetting_companydefault_title","companyDefault","changepassword","resetpassword","anonymize","deleteandanonymize","resetdeactivationtimer","accountIdleExpirationInDays","angular.module","kbapp","$locationProvider","$httpProvider","$urlRouterProvider","$provide","$animateProvider","$compileProvider","html5Mode","debugInfoEnabled","commentDirectivesEnabled","cssClassDirectivesEnabled","interceptors","decorator","$delegate","cause","sfdccpq","licenseKbmax","license3D","canModifyScenes","isChannelAdmin","canModifyCurrencies","otherwise","classNameFilter","stateHelper","abstract","onLoginPage","lazyLoad","injector","isEpicorEmployee","isSfdcCustomTheme","$win","isHoverSupported","matchMedia","isIE","navigator","userAgent","realProp","supportsFullscreen","lastMove","mouseMoveWait","onmousemove","checkTime","setInterval","isAnonymous","models","rules"],"mappings":"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","file":"app.min.js","sourcesContent":["var app = (function (exports, enums, angular, _tools, flatpickr, Tether, _rules, kb3d, Q, signalR, Big) {\n 'use strict';\n\n function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }\n\n function _interopNamespace(e) {\n if (e && e.__esModule) return e;\n var n = Object.create(null);\n if (e) {\n Object.keys(e).forEach(function (k) {\n if (k !== 'default') {\n var d = Object.getOwnPropertyDescriptor(e, k);\n Object.defineProperty(n, k, d.get ? d : {\n enumerable: true,\n get: function () {\n return e[k];\n }\n });\n }\n });\n }\n n['default'] = e;\n return Object.freeze(n);\n }\n\n var enums__namespace = /*#__PURE__*/_interopNamespace(enums);\n var flatpickr__default = /*#__PURE__*/_interopDefaultLegacy(flatpickr);\n var Tether__default = /*#__PURE__*/_interopDefaultLegacy(Tether);\n var Q__namespace = /*#__PURE__*/_interopNamespace(Q);\n var Big__default = /*#__PURE__*/_interopDefaultLegacy(Big);\n\n // tslint:disable:variable-name\n var Token = /** @class */ (function () {\n function Token(key) {\n this.key = key;\n }\n Token.withKey = function (key) {\n var token = this[key];\n if (!token)\n token = new Token(key); // throw new Error(`Could not find token for key '${key}'`);\n return token;\n };\n // libraries\n Token.AdminLib = new Token(\"adminLib\");\n Token.Creator = new Token(\"creator\");\n Token.HandsontableLib = new Token(\"handsontableLib\");\n Token.HighchartsLib = new Token(\"highchartsLib\");\n Token.MarkdownDeepLib = new Token(\"markdownDeepLib\");\n Token.MonacoLoaderLib = new Token(\"monacoLoaderLib\");\n Token.Recaptcha = new Token(\"Recaptcha\");\n Token.SnapLib = new Token(\"snapLib\");\n Token.Viewer = new Token(\"viewer\");\n // angular built-ins\n Token.$Animate = new Token(\"$animate\");\n Token.$Scope = new Token(\"$scope\");\n Token.$Location = new Token(\"$location\");\n Token.$Http = new Token(\"$http\");\n Token.$RootScope = new Token(\"$rootScope\");\n Token.$Timeout = new Token(\"$timeout\");\n Token.$Q = new Token(\"$q\");\n Token.$Window = new Token(\"$window\");\n Token.$Document = new Token(\"$document\");\n Token.$Filter = new Token(\"$filter\");\n Token.$Injector = new Token(\"$injector\");\n Token.$Interval = new Token(\"$interval\");\n Token.$TemplateCache = new Token(\"$templateCache\");\n Token.$TemplateRequest = new Token(\"$templateRequest\");\n Token.$Compile = new Token(\"$compile\");\n Token.$Sce = new Token(\"$sce\");\n Token.$Locale = new Token(\"$locale\");\n Token.$CookieStore = new Token(\"$cookieStore\");\n Token.$Sanitize = new Token(\"$sanitize\");\n Token.PromiseTracker = new Token(\"promiseTracker\");\n Token.$OcLazyLoad = new Token(\"$ocLazyLoad\");\n // ui router\n Token.$State = new Token(\"$state\");\n Token.$Transitions = new Token(\"$transitions\");\n Token.$StateParams = new Token(\"$stateParams\");\n // resolves\n Token.Model = new Token(\"model\");\n Token.ProductResolve = new Token(\"productResolve\");\n Token.Categories = new Token(\"categories\");\n Token.Header = new Token(\"header\");\n Token.SsoGroups = new Token(\"ssoGroups\");\n // animations\n Token.KbRise = new Token(\".kb-rise\");\n // components\n Token.KbActionSelect = new Token(\"kbActionSelect\");\n Token.KbAllowFraction = new Token(\"kbAllowFraction\");\n Token.KbAtom = new Token(\"kbAtom\");\n Token.KbAttachments = new Token(\"kbAttachments\");\n Token.KbAutoComplete = new Token(\"kbAutoComplete\");\n Token.KbAvatar = new Token(\"kbAvatar\");\n Token.KbAvatarSelect = new Token(\"kbAvatarSelect\");\n Token.KbButton = new Token(\"kbButton\");\n Token.KbCheckbox = new Token(\"kbCheckbox\");\n Token.KbColorPicker = new Token(\"kbColorPicker\");\n Token.KbColumn = new Token(\"kbColumn\");\n Token.KbContent = new Token(\"kbContent\");\n Token.KbComments = new Token(\"kbComments\");\n Token.KbDataGrid = new Token(\"kbDataGrid\");\n Token.KbDatePicker = new Token(\"kbDatePicker\");\n Token.KbDropdown = new Token(\"kbDropdown\");\n Token.KbEdit = new Token(\"kbEdit\");\n Token.KbEllipsis = new Token(\"kbEllipsis\");\n Token.KbExpander = new Token(\"kbExpander\");\n Token.KbExpanderGroup = new Token(\"kbExpanderGroup\");\n Token.KbField = new Token(\"kbField\");\n Token.KbFieldControl = new Token(\"kbFieldControl\");\n Token.KbFocus = new Token(\"kbFocus\");\n Token.KbForm = new Token(\"kbForm\");\n Token.KbIcon = new Token(\"kbIcon\");\n Token.KbIf = new Token(\"kbIf\");\n Token.KbIfDelay = new Token(\"kbIfDelay\");\n Token.KbImageSelect = new Token(\"kbImageSelect\");\n Token.KbInclude = new Token(\"kbInclude\");\n Token.KbInfiniteScroll = new Token(\"kbInfiniteScroll\");\n Token.KbLabel = new Token(\"kbLabel\");\n Token.KbList = new Token(\"kbList\");\n Token.KbListItem = new Token(\"kbListItem\");\n Token.KbMarkdownViewer = new Token(\"kbMarkdownViewer\");\n Token.KbMax = new Token(\"kbMax\");\n Token.KbMediaList = new Token(\"kbMediaList\");\n Token.KbMediaManager = new Token(\"kbMediaManager\");\n Token.KbMediaSelect = new Token(\"kbMediaSelect\");\n Token.KbMediaViewer = new Token(\"kbMediaViewer\");\n Token.KbMenu = new Token(\"kbMenu\");\n Token.KbMenuItem = new Token(\"kbMenuItem\");\n Token.KbMin = new Token(\"kbMin\");\n Token.KbMoney = new Token(\"kbMoney\");\n Token.KbMultiAutoComplete = new Token(\"kbMultiAutoComplete\");\n Token.KbMultiSelect = new Token(\"kbMultiSelect\");\n Token.KbImageMultiSelect = new Token(\"kbImageMultiSelect\");\n Token.KbNumberbox = new Token(\"kbNumberbox\");\n Token.KbOption = new Token(\"kbOption\");\n Token.KbPage = new Token(\"kbPage\");\n Token.KbPageTitle = new Token(\"kbPageTitle\");\n Token.KbPassword = new Token(\"kbPassword\");\n Token.KbPrivacyPolicy = new Token(\"kbPrivacyPolicy\");\n Token.KbProgress = new Token(\"kbProgress\");\n Token.KbRadio = new Token(\"kbRadio\");\n Token.KbResize = new Token(\"kbResize\");\n Token.KbRipple = new Token(\"kbRipple\");\n Token.KbScope = new Token(\"kbScope\");\n Token.KbSearchGrid = new Token(\"kbSearchGrid\");\n Token.KbSelect = new Token(\"kbSelect\");\n Token.KbSfdcHeader = new Token(\"kbSfdcHeader\");\n Token.KbSlide = new Token(\"kbSlide\");\n Token.KbSlider = new Token(\"kbSlider\");\n Token.KbSpinner = new Token(\"kbSpinner\");\n Token.KbSpinnerElement = new Token(\"kbSpinnerElement\");\n Token.KbSrcOnError = new Token(\"kbSrcOnError\");\n Token.KbSvgViewer = new Token(\"kbSvgViewer\");\n Token.KbTab = new Token(\"kbTab\");\n Token.KbTabs = new Token(\"kbTabs\");\n Token.KbTextarea = new Token(\"kbTextarea\");\n Token.KbTextbox = new Token(\"kbTextbox\");\n Token.KbToggle = new Token(\"kbToggle\");\n Token.KbToggleButton = new Token(\"KbToggleButton\");\n Token.KbTooltip = new Token(\"kbTooltip\");\n Token.KbTransclude = new Token(\"kbTransclude\");\n Token.KbTree = new Token(\"kbTree\");\n Token.KbTreeNode = new Token(\"kbTreeNode\");\n Token.KbUiObject = new Token(\"kbUiObject\");\n Token.KbUpload = new Token(\"kbUpload\");\n Token.KbValidationMessages = new Token(\"kbValidationMessages\");\n // filters\n Token.AssetFilter = new Token(\"asset\");\n Token.BytesFilter = new Token(\"bytes\");\n Token.EnumFilter = new Token(\"enum\");\n Token.FileIconFilter = new Token(\"fileIcon\");\n Token.FileIdFilter = new Token(\"fileId\");\n Token.FxConvertFilter = new Token(\"fxConvert\");\n Token.GetFileExtensionFilter = new Token(\"getFileExtension\");\n Token.GetFilenameFilter = new Token(\"getFilename\");\n Token.HasRoleFilter = new Token(\"hasRole\");\n Token.IconFilter = new Token(\"icon\");\n Token.IsAdminOrCompanyAdminFilter = new Token(\"isAdminOrCompanyAdmin\");\n Token.KbCurrencyFilter = new Token(\"kbCurrency\");\n Token.KbDateTimeFilter = new Token(\"kbDateTime\");\n Token.KbDateFilter = new Token(\"kbDate\");\n Token.LeadTimeFilter = new Token(\"leadTime\");\n Token.LocFilter = new Token(\"loc\");\n Token.LogIconFilter = new Token(\"logIcon\");\n Token.MediaFilter = new Token(\"media\");\n Token.NotificationIconFilter = new Token(\"notificationIcon\");\n Token.NumberFormateFilter = new Token(\"numberFormat\");\n Token.ProfileImageFilter = new Token(\"profileImage\");\n Token.QuoteProductImageFilter = new Token(\"quoteProductImage\");\n Token.RangeFilter = new Token(\"range\");\n Token.RawTextFilter = new Token(\"rawText\");\n Token.ShadeFilter = new Token(\"shade\");\n Token.SmartColorFilter = new Token(\"smartColor\");\n Token.ThemeColorFilter = new Token(\"themeColor\");\n Token.ThumbFilter = new Token(\"thumb\");\n Token.TruncateFilter = new Token(\"truncate\");\n Token.TrustAsHtmlFilter = new Token(\"trustAsHtml\");\n // interceptors\n Token.CacheBusterInterceptor = new Token(\"cacheBusterInterceptor\");\n Token.ErrorInterceptor = new Token(\"errorInterceptor\");\n Token.SecurityInterceptor = new Token(\"securityInterceptor\");\n // services\n Token.ApiService = new Token(\"apiService\");\n Token.AuthService = new Token(\"authService\");\n Token.Base64Service = new Token(\"base64Service\");\n Token.BundleLoaderService = new Token(\"bundleLoaderService\");\n Token.ClaraSceneService = new Token(\"claraSceneService\");\n Token.CrudService = new Token(\"crudService\");\n Token.DialogService = new Token(\"dialogService\");\n Token.DrawerService = new Token(\"drawerService\");\n Token.KbService = new Token(\"kbService\");\n Token.QuoteService = new Token(\"quoteService\");\n Token.RuleService = new Token(\"ruleService\");\n Token.SearchService = new Token(\"searchService\");\n Token.SecurityRetryService = new Token(\"securityRetryService\");\n Token.SfdcService = new Token(\"sfdcService\");\n Token.SignalRService = new Token(\"signalRService\");\n Token.StorageService = new Token(\"storageService\");\n Token.TelemetryService = new Token(\"telemetryService\");\n Token.ThemeService = new Token(\"themeService\");\n Token.UploadService = new Token(\"uploadService\");\n Token.InteractionService = new Token(\"interactionService\");\n // views\n Token.ContactView = new Token(\"contactView\");\n Token.ContactsView = new Token(\"contactsView\");\n Token.CrudView = new Token(\"crudView\");\n Token.CustomerView = new Token(\"customerView\");\n Token.CustomersView = new Token(\"customersView\");\n Token.DialogView = new Token(\"dialogView\");\n Token.NotificationsView = new Token(\"notificationsView\");\n Token.DrawerView = new Token(\"drawerView\");\n Token.LoginView = new Token(\"loginView\");\n Token.PortalView = new Token(\"portalView\");\n Token.PrivacyPolicyView = new Token(\"privacyPolicyView\");\n Token.ConfiguratorView = new Token(\"configuratorView\");\n Token.ProductView = new Token(\"productView\");\n Token.ProductsView = new Token(\"productsView\");\n Token.ProductCompareView = new Token(\"productCompareView\");\n Token.ConfiguredProductsView = new Token(\"configuredProductsView\");\n Token.QuoteView = new Token(\"quoteView\");\n Token.QuotesView = new Token(\"quotesView\");\n Token.SceneEmbedView = new Token(\"sceneEmbedView\");\n Token.SearchView = new Token(\"searchView\");\n Token.ChangePasswordView = new Token(\"changePasswordView\");\n Token.UserActivationView = new Token(\"userActivationView\");\n Token.UserView = new Token(\"userView\");\n return Token;\n }());\n\n function NgService(args) {\n return function (target) {\n DI.register(\"service\", args, target);\n };\n }\n function NgAnimation(args) {\n return function (target) {\n DI.register(\"animation\", args, target);\n };\n }\n function NgComponent(args) {\n return function (target) {\n DI.register(\"directive\", args, target);\n };\n }\n function NgInterceptor(args) {\n return function (target) {\n DI.register(\"factory\", args, target);\n };\n }\n function NgFilter(args) {\n return function (target) {\n DI.register(\"filter\", args, target);\n };\n }\n function NgView(args) {\n return function (target) {\n DI.register(\"controller\", args, target);\n };\n }\n var DI = /** @class */ (function () {\n function DI() {\n }\n DI.register = function (ngType, args, constructor) {\n var _a, _b, _c;\n if (DI.db.hasOwnProperty(args.token.key)) {\n throw new Error(\"A type with key \".concat(args.token.key, \" has already been registered\"));\n }\n args.dependencies = args.dependencies || [];\n args.resolves = args.resolves || [];\n args.libraries = args.libraries || [];\n if (args.inherit) {\n for (var _i = 0, _d = args.inherit; _i < _d.length; _i++) {\n var baseToken = _d[_i];\n var baseInject = DI.get(baseToken);\n if (baseInject.dependencies)\n (_a = args.dependencies).unshift.apply(_a, baseInject.dependencies);\n if (baseInject.resolves)\n (_b = args.resolves).unshift.apply(_b, baseInject.resolves);\n if (baseInject.libraries)\n (_c = args.libraries).unshift.apply(_c, baseInject.libraries);\n }\n }\n var resolveObject = args.resolves &&\n args.resolves\n .reduce(function (p, c) {\n p[c.name] = [].concat.apply([], c.dependencies.map(function (d) { return d.key; })).concat(c.fn.bind(constructor));\n return p;\n }, {});\n if (args.libraries) {\n resolveObject[\"scripts\"] = [Token.BundleLoaderService.key, function (bundleLoader) {\n return bundleLoader.load(args.libraries);\n }];\n }\n var ngInject = {\n token: args.token,\n ngType: ngType,\n dependencies: args.dependencies,\n resolves: args.resolves,\n construct: [].concat(args.dependencies.map(function (d) { return d.key; })).concat(function () {\n var a = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n a[_i] = arguments[_i];\n }\n return new (constructor.bind.apply(constructor, __spreadArray([void 0], a, false)))();\n }),\n resolveObject: resolveObject,\n libraries: args.libraries\n };\n DI.db[args.token.key] = ngInject;\n };\n DI.get = function (token) {\n return DI.db[token.key];\n };\n DI.fillAngularApp = function (app) {\n for (var key in DI.db) {\n var i = DI.db[key];\n if (!i.addedToApp) {\n app[i.ngType](i.token.key, i.construct);\n i.addedToApp = true;\n }\n }\n };\n DI.db = {};\n return DI;\n }());\n\n (function (eBundle) {\n eBundle[\"app\"] = \"app\";\n eBundle[\"admin\"] = \"admin\";\n })(exports.eBundle || (exports.eBundle = {}));\n var Dirs = /** @class */ (function () {\n function Dirs() {\n }\n Dirs.component = function (name, bundle) {\n if (bundle === void 0) { bundle = exports.eBundle.app; }\n return this.get(\"html/\".concat(bundle, \"/\").concat(name, \".component.html\"));\n };\n Dirs.template = function (name, bundle) {\n if (bundle === void 0) { bundle = exports.eBundle.app; }\n return this.get(\"html/\".concat(bundle, \"/\").concat(name, \".html\"));\n };\n Dirs.view = function (name, bundle) {\n if (bundle === void 0) { bundle = exports.eBundle.app; }\n return this.get(\"html/\".concat(bundle, \"/\").concat(name, \".view.html\"));\n };\n Dirs.get = function (url) {\n return window.html[url];\n };\n return Dirs;\n }());\n\n var StateHelper = /** @class */ (function () {\n function StateHelper($stateProvider, bundle) {\n this.$stateProvider = $stateProvider;\n this.bundle = bundle;\n }\n StateHelper.prototype.getPluralName = function (name) {\n var plural = name;\n if (!name.endsWith(\"s\")) {\n if (name.endsWith(\"y\")) {\n plural = name.slice(0, -1) + \"ies\";\n }\n else {\n plural = name + \"s\";\n }\n }\n return plural;\n };\n StateHelper.prototype.addState = function (o) {\n var _this = this;\n var ngInject = o.view && DI.get(o.view);\n var resolve = ngInject && Object.assign({}, ngInject.resolveObject);\n var nameSegment = o.name.split(\".\").last();\n var kebab = nameSegment.toKebabCase();\n if (!o.allowAnonymous && resolve) {\n resolve[\"auth\"] = [\n Token.AuthService.key,\n function (authService) {\n return authService.authPromise;\n }\n ];\n }\n else if (o.allowAnonymous) {\n if (!o.data)\n o.data = {};\n o.data.allowAnonymous = true;\n }\n this.$stateProvider.state(o.name, {\n url: angular.isDefined(o.url) ? o.url : \"/\".concat(kebab),\n params: o.params,\n template: function () { return o.template || Dirs.get(o.templateUrl) || Dirs.view(o.templateName || kebab, _this.bundle); },\n // templateUrl: o.templateUrl || Dirs.view(o.templateName || kebab, this.bundle),\n controller: ngInject && ngInject.construct,\n resolve: resolve,\n data: o.data,\n reloadOnSearch: o.reloadOnSearch,\n parent: o.parent\n });\n };\n StateHelper.prototype.addSearchState = function (o) {\n var nameSegment = o.name.split(\".\").last();\n this.addState({\n name: o.name,\n view: o.view,\n url: o.url ? o.url : \"/\".concat(nameSegment.toKebabCase(), \"?search&searchid\"),\n params: {\n search: { dynamic: true },\n searchid: { dynamic: true }\n }\n });\n };\n StateHelper.prototype.addCrudStates = function (o) {\n var nameSegment = o.name.split(\".\").last();\n var nameKebab = nameSegment.toKebabCase();\n var pluralName = this.getPluralName(nameSegment);\n var baseUrl = \"/\".concat(pluralName.toKebabCase());\n var statePrefix = o.name.substring(0, o.name.lastIndexOf(\".\"));\n var editStatePrefix = \"\".concat(statePrefix).concat(o.isSnapBased ? \".base\" : \"\");\n this.addSearchState({\n name: \"\".concat(statePrefix, \".\").concat(pluralName),\n view: o.searchView\n });\n var newStateConfig = {\n name: \"\".concat(editStatePrefix, \".\").concat(nameSegment, \"New\"),\n url: \"\".concat(baseUrl, \"/new\"),\n templateName: nameKebab,\n templateUrl: o.templateUrl,\n template: o.template,\n view: o.view,\n data: { viewType: enums.eViewType.new }\n };\n if (o.newStateParams)\n newStateConfig.url += \"/:\" + o.newStateParams.join(\"/:\");\n this.addState(newStateConfig);\n this.addState({\n name: \"\".concat(editStatePrefix, \".\").concat(nameSegment, \"Edit\"),\n url: \"\".concat(baseUrl, \"/:id\").concat(o.isSnapBased ? \"?sel\" : \"\"),\n templateName: nameKebab,\n templateUrl: o.templateUrl,\n template: o.template,\n view: o.view,\n data: { viewType: enums.eViewType.edit },\n reloadOnSearch: !o.isSnapBased\n });\n };\n return StateHelper;\n }());\n\n var KbRise = /** @class */ (function () {\n function KbRise($timeout) {\n var _this = this;\n this.$timeout = $timeout;\n var duration = function (distance) {\n return Math.max(Math.min(distance / 2, 350), 150);\n };\n var show = function (element, done) {\n var origOpacity = element.css(\"opacity\");\n var origOverflow = element.css(\"overflow\");\n element.css(\"opacity\", 0);\n element.removeClass(\"ng-hide\");\n var finalSetHeight = element.hasClass(\"kb-rise--full-height\") ? element.css(\"max-height\") : \"auto\";\n element.css(\"height\", finalSetHeight);\n var autoHeight = element.height();\n if (!autoHeight)\n autoHeight = \"95%\";\n element.height(0);\n element.css(\"opacity\", origOpacity);\n element.animate({ height: autoHeight }, duration(autoHeight), function () {\n element.css(\"height\", finalSetHeight);\n done();\n });\n };\n var hide = function (element, done) {\n _this.autoHeight = element.height();\n element.animate({ height: 0 }, duration(_this.autoHeight), function () {\n element.css(\"height\", 0);\n done();\n });\n };\n this.beforeAddClass = function (element, className, done) {\n if (className == \"ng-hide\") {\n hide(element, done);\n }\n };\n this.removeClass = function (element, className, done) {\n if (className == \"ng-hide\") {\n show(element, done);\n }\n };\n this.enter = function (element, done) {\n show(element, done);\n };\n this.leave = function (element, done) {\n hide(element, done);\n };\n }\n KbRise = __decorate([\n NgAnimation({\n token: Token.KbRise,\n dependencies: [\n Token.$Timeout\n ]\n })\n ], KbRise);\n return KbRise;\n }());\n // export class kbSlide extends ngAnimation {\n // public injection(): any[] {\n // return [\n // Token.$Timeout,\n // ($timeout) => { return new kbSlide($timeout) }\n // ]\n // }\n // constructor($timeout: ng.ITimeoutService) {\n // super();\n // var show = (element: ng.IAugmentedJQuery , done) => {\n // element.removeClass(\"ng-hide\");\n // element.css(\"width\", \"auto\");\n // var autoWidth: any = element.width();\n // if (!autoWidth) autoWidth = \"95%\";\n // element.width(0);\n // element.animate({ \"width\": autoWidth }, 150, \"linear\", () => {\n // element.css(\"width\", \"auto\");\n // done();\n // });\n // }\n // var hide = (element: ng.IAugmentedJQuery, done) => {\n // this.autoWidth = element.width();\n // element.animate({ \"width\": 0 }, 150, () => {\n // element.css(\"width\", 0);\n // done();\n // });\n // }\n // this.beforeAddClass = (element: ng.IAugmentedJQuery, className: string, done) => {\n // if (className == \"ng-hide\") {\n // hide(element, done);\n // }\n // }\n // this.removeClass = (element: ng.IAugmentedJQuery, className: string, done) => {\n // if (className == \"ng-hide\") {\n // show(element, done);\n // }\n // }\n // }\n // private autoWidth: number;\n // }\n // export class kbFade extends ngAnimation {\n // public injection(): any[] {\n // return [\n // () => { return new kbFade() }\n // ]\n // }\n // constructor() {\n // super();\n // this.addClass = (element, className, done) => {\n // if (className == \"ng-hide\") {\n // var origOpacity = element.css(\"opacity\");\n // element.animate({ \"opacity\": 0 }, 150, () => {\n // element.hide();\n // element.css(\"opacity\", origOpacity);\n // done();\n // });\n // }\n // }\n // this.removeClass = (element, className, done) => {\n // if (className == \"ng-hide\") {\n // var origOpacity = element.css(\"opacity\");\n // element.css(\"opacity\", 0);\n // element.show();\n // var to = \"1\";\n // if (origOpacity && origOpacity != \"0\") {\n // to = origOpacity;\n // }\n // element.animate({ \"opacity\": to }, 150, () => {\n // element.show();\n // element.css(\"opacity\", to);\n // done();\n // });\n // }\n // }\n // }\n // }\n\n var Directive = /** @class */ (function () {\n function Directive() {\n }\n return Directive;\n }());\n\n var KbActionSelect = /** @class */ (function (_super) {\n __extends(KbActionSelect, _super);\n function KbActionSelect($q, $http) {\n var _this = _super.call(this) || this;\n _this.restrict = \"EA\";\n _this.template = Dirs.component(\"kb-action-select\");\n _this.scope = {\n source: \"=\",\n valueField: \"@\",\n defaultLabel: \"@\",\n icon: \"@\",\n onAction: \"=\"\n };\n _this.replace = true;\n _this.link = function (scope, element, atts, ngModel) {\n scope._actionSelect = \"\";\n scope.$watch(\"_actionSelect\", function (newValue) {\n if (!newValue)\n return;\n scope.onAction(newValue);\n scope._actionSelect = \"\";\n });\n };\n return _this;\n }\n KbActionSelect = __decorate([\n NgComponent({\n token: Token.KbActionSelect,\n dependencies: [\n Token.$Q,\n Token.$Http,\n ]\n })\n ], KbActionSelect);\n return KbActionSelect;\n }(Directive));\n\n var KbAllowFractions = /** @class */ (function (_super) {\n __extends(KbAllowFractions, _super);\n function KbAllowFractions() {\n var _this = _super.call(this) || this;\n _this.restrict = \"A\";\n _this.require = \"ngModel\";\n _this.link = function (scope, elem, attr, ctrl) {\n var maxValidator = function (value) {\n var allowFractions = scope.$eval(attr.kbAllowFractions) || true;\n if (!allowFractions && value % 1 != 0) {\n var newValue = Math.round(value);\n $(elem).val(newValue);\n return newValue;\n }\n return value;\n };\n ctrl.$parsers.push(maxValidator);\n ctrl.$formatters.push(maxValidator);\n };\n return _this;\n }\n KbAllowFractions = __decorate([\n NgComponent({\n token: Token.KbAllowFraction,\n dependencies: [\n Token.$Q,\n Token.$Http,\n ]\n })\n ], KbAllowFractions);\n return KbAllowFractions;\n }(Directive));\n\n var KbAtom = /** @class */ (function (_super) {\n __extends(KbAtom, _super);\n function KbAtom($timeout) {\n var _this = _super.call(this) || this;\n _this.restrict = \"E\";\n _this.template = Dirs.component(\"kb-atom\");\n _this.scope = false;\n _this.replace = true;\n _this.transclude = {\n display: \"?kbAtomDisplay\",\n edit: \"?kbAtomEdit\"\n };\n _this.link = function (scope, element, atts) {\n scope._editMode = scope.$eval(atts.editMode) == true;\n var guid = _tools.Utils.shortId();\n var eventName = \"click.kbAtom.\" + guid;\n var documentClick = function (e) {\n // ignore if it was this kbAtom that was clicked\n if (!$(e.target).is(element) && !$.contains(element[0], e.target)) {\n scope.$apply(function () {\n scope._editing = false;\n });\n $(document).off(eventName, documentClick);\n }\n };\n var changeEditMode = function (val) {\n scope._editing = val;\n if (val) {\n scope._displayClick = function ($event) {\n };\n // scope._editClick = ($event: ng.IAngularEvent) => {\n // }\n }\n else {\n scope._displayClick = function ($event) {\n if ($(element).hasClass(\"disabled\") || $(element).attr(\"disabled\"))\n return;\n // $event.stopPropagation();\n scope._editing = true;\n $(document).on(eventName, documentClick);\n };\n // scope._editClick = ($event: ng.IAngularEvent) => {\n // $event.stopPropagation();\n // }\n }\n };\n var editAtt = atts.editMode;\n if (editAtt) {\n scope.$watch(function () { return scope.$eval(editAtt); }, changeEditMode);\n }\n else {\n changeEditMode(false);\n }\n scope.$on(\"$destroy\", function () {\n $(document).off(eventName, documentClick);\n });\n };\n return _this;\n }\n KbAtom = __decorate([\n NgComponent({\n token: Token.KbAtom,\n dependencies: [\n Token.$Timeout\n ]\n })\n ], KbAtom);\n return KbAtom;\n }(Directive));\n\n var KbAttachments = /** @class */ (function (_super) {\n __extends(KbAttachments, _super);\n function KbAttachments($rootScope, dialogService, $http, $q, uploadService, storageService) {\n var _this = _super.call(this) || this;\n _this.$rootScope = $rootScope;\n _this.dialogService = dialogService;\n _this.$http = $http;\n _this.$q = $q;\n _this.uploadService = uploadService;\n _this.storageService = storageService;\n _this.replace = false;\n _this.template = Dirs.component(\"kb-attachments\");\n _this.restrict = \"E\";\n _this.scope = {\n objectId: \"=\",\n tableName: \"@\",\n relationshipProperty: \"@\",\n files: \"=\",\n fileEntityPath: \"@\",\n canChange: \"=\",\n canAdd: \"=\",\n downloadFile: \"=\"\n };\n _this.link = function (scope, element, atts) {\n if (typeof scope.canChange == \"undefined\") {\n scope.canChange = $rootScope.user.canModifyAllAttachments || $rootScope.user.canAddAttachments;\n }\n if (typeof scope.secureFileDownloadUrl == \"undefined\")\n scope.secureFileDownloadUrl = \"file/download\";\n var displayDialog = function (callback, file, name, description, source) {\n if (name === void 0) { name = \"\"; }\n if (description === void 0) { description = \"\"; }\n var fileInfo = scope.$new(true);\n if (!file)\n file = { name: \"\" };\n fileInfo.model = {\n fileName: file.name,\n name: name,\n description: description,\n source: source\n };\n fileInfo.canViewMedia = _this.$rootScope.context.user.canModifyMedia;\n dialogService.dialog({\n type: enums.eInputDialogType.html,\n template: Dirs.view(\"dialog-edit-attachment\"),\n scope: fileInfo,\n buttons: [\n new enums.DialogButton(loc.ok, _tools.icons.submit, function () {\n callback(fileInfo.model.name, fileInfo.model.description, file, fileInfo.model.source);\n }),\n new enums.DialogButton(loc.cancel, _tools.icons.cancel)\n ]\n });\n fileInfo.uploadNewAttachment = function () {\n _this.uploadService.promptUserToChooseFile(atts.accept).then(function (selectedFile) {\n if (file.name == fileInfo.model.name || !fileInfo.model.name) {\n fileInfo.model.name = selectedFile.name;\n }\n fileInfo.model.fileName = selectedFile.name;\n fileInfo.model.source = enums.eFileSource.uploaded;\n file = selectedFile;\n });\n };\n fileInfo.selectMediaFile = function () {\n var name = fileInfo.model.name;\n var description = fileInfo.model.description;\n dialogService.mediaSelect({\n buttons: [\n new enums.MediaDialogButton(loc.ok, _tools.icons.success, function (args) {\n if (!name || name == file.name) {\n fileInfo.model.name = args.selectedItem.name;\n }\n fileInfo.model.fileName = args.selectedItem.name;\n fileInfo.model.source = enums.eFileSource.media;\n file = args.selectedItem;\n }),\n new enums.MediaDialogButton(loc.cancel, _tools.icons.cancel, function (args) {\n })\n ]\n });\n };\n };\n if (!scope.downloadFile) {\n scope.downloadFile = function (item) {\n if (typeof window != \"undefined\") {\n window.open(storageService.getMediaUrl(item.filePath));\n }\n };\n }\n scope._uploadFile = function (item) {\n if (!item) {\n item = {\n filePath: \"\",\n name: \"\",\n description: \"\",\n source: null\n };\n }\n displayDialog(function (name, description, file, source) {\n var newFileEntity = {\n name: name,\n description: description,\n id: item.id,\n filePath: file.name,\n // idCompany: $rootScope.company.id,\n // idUser: $rootScope.user.id,\n createdBy: $rootScope.user.id,\n // tableName: scope.tableName,\n createdByName: $rootScope.user.firstName + \" \" + $rootScope.user.lastName,\n source: null,\n status: enums.eFileStatus.complete\n };\n if (source)\n newFileEntity.source = source;\n if (newFileEntity.source == enums.eFileSource.media)\n newFileEntity.filePath = file.name;\n if (scope.objectId && scope.relationshipProperty) {\n newFileEntity[scope.relationshipProperty] = scope.objectId;\n }\n if (file && source != enums.eFileSource.media) {\n var url = scope.postUrl;\n var deferred_1 = $q.defer();\n dialogService.alert({\n promise: deferred_1.promise,\n successMsg: \"Upload complete\"\n });\n var uploadProgress = function (evt) {\n if (evt.lengthComputable) {\n deferred_1.notify(Math.round(evt.loaded * 100 / evt.total));\n }\n else {\n deferred_1.notify(\"Unknown File Size\");\n }\n };\n var uploadComplete = function (result) {\n deferred_1.resolve();\n if (item.id) {\n $.extend(item, newFileEntity);\n }\n else {\n newFileEntity.id = result.id;\n scope.files.push(newFileEntity);\n }\n };\n var uploadFailed = function () {\n deferred_1.reject(\"Upload failed\");\n };\n _this.uploadService.uploadAttachment(file, newFileEntity, scope.fileEntityPath)\n .then(uploadComplete, uploadFailed, uploadProgress);\n }\n else {\n if (item.id) {\n $.extend(item, newFileEntity);\n $http.put(scope.fileEntityPath, newFileEntity);\n }\n else {\n scope.files.push(newFileEntity);\n $http.post(scope.fileEntityPath, newFileEntity);\n }\n }\n }, { name: item.filePath, isFromMedia: true }, item.name, item.description, item.source);\n };\n scope.delete = function (item) {\n _this.dialogService.confirm(loc.msg_confirmdelete, function () {\n scope.files.remove(item);\n _this.$http.delete(scope.fileEntityPath + \"/\" + item.id);\n });\n };\n };\n return _this;\n }\n KbAttachments = __decorate([\n NgComponent({\n token: Token.KbAttachments,\n dependencies: [\n Token.$RootScope,\n Token.DialogService,\n Token.$Http,\n Token.$Q,\n Token.UploadService,\n Token.StorageService\n ]\n })\n ], KbAttachments);\n return KbAttachments;\n }(Directive));\n\n /**\n * Acts as a base class to directives that work together with kbField to manage focus and common setup\n */\n var KbInput = /** @class */ (function (_super) {\n __extends(KbInput, _super);\n function KbInput($timeout) {\n var _this = _super.call(this) || this;\n _this.$timeout = $timeout;\n _this.restrict = \"E\";\n _this.replace = true;\n _this.scope = {\n ngModel: \"=\",\n ngDisabled: \"=?\",\n ngModelOptions: \"=?\",\n ngChange: \"&\",\n ngBlur: \"&\",\n touched: \"&\",\n ignoreField: \"=?\",\n textColor: \"=?\",\n backgroundColor: \"=?\",\n heightOverride: \"=?\"\n };\n _this.require = [\"ngModel\", \"?^^kbField\"];\n _this.link = function (s, e, a, c) { return _this.kbInputLinkFn(s, e, a, c); };\n return _this;\n }\n KbInput.prototype.kbInputLinkFn = function (scope, element, atts, controllers, shouldFloat, isEmpty) {\n var _this = this;\n if (shouldFloat === void 0) { shouldFloat = true; }\n var ngModelCtrl = controllers[0];\n var kbField = null;\n if (!scope.ignoreField) {\n kbField = controllers.length > 1 ? controllers.last() : null;\n }\n if (kbField) { //register our input ngModel with kbField\n kbField.setShouldFloat(shouldFloat);\n }\n if (!isEmpty) {\n isEmpty = function (val) {\n return (val == null || val.toString().length == 0);\n };\n }\n var ngModelPipelineCheckValue = function (val) {\n if (kbField)\n kbField.setHasValue(!isEmpty(val) && !(Array.isArray(val) && !val.length));\n return val;\n };\n ngModelCtrl.$parsers.push(ngModelPipelineCheckValue);\n ngModelCtrl.$formatters.push(ngModelPipelineCheckValue);\n ngModelCtrl.$viewChangeListeners.push(function () {\n //for some controls, blur is not the right time to consider whether the control has been touched (like select controls).\n //so we also track it here.\n if (scope.touched) {\n scope.touched();\n }\n });\n var focusin = function (e) {\n if (kbField)\n kbField.setFocused(true);\n };\n var focusout = function () {\n if (kbField) {\n kbField.setFocused(false);\n }\n if (scope.touched) {\n scope.touched();\n }\n };\n element.on(\"focusin\", focusin);\n element.on(\"focusout\", focusout);\n // for some reason the ngChange is getting run before the model in the parent controller\n // is being updated by the value change, so we need to do this trick to wait until\n // everything is done before firing the ng-change\n scope._ngChange = function () {\n _this.$timeout(function () {\n scope.ngChange();\n }, 0);\n };\n // bind keyboard event: esc(27)\n var el = element;\n if (!el.is(\"input\")) {\n el = el.find(\"input\");\n }\n if (el && el.length > 0) {\n el.on(\"keydown\", function (e) {\n if (e.which == 27) {\n el.blur();\n }\n });\n }\n scope._setHasValue = function (hasValue) {\n if (kbField) {\n kbField.setHasValue(hasValue);\n }\n };\n scope.$on(\"$destroy\", function () {\n if (kbField) {\n kbField.setFocused(false);\n kbField.setHasValue(false);\n }\n element.off();\n });\n };\n return KbInput;\n }(Directive));\n\n var KbAutoComplete = /** @class */ (function (_super) {\n __extends(KbAutoComplete, _super);\n function KbAutoComplete($q, $http, $timeout) {\n var _this = _super.call(this, $timeout) || this;\n _this.template = Dirs.component(\"kb-auto-complete\");\n _this.scope = _tools.Utils.extend(_this.scope, {\n source: \"&\",\n data: \"=?\",\n getLabel: \"&\",\n editable: \"=?\",\n valueField: \"@\",\n labelField: \"@\",\n defaultLabel: \"@\",\n headerTemplate: \"@\",\n itemStyle: \"@\",\n throttle: \"@\",\n minCharacters: \"=?\",\n icon: \"@\",\n submit: \"&\",\n placeholder: \"@\",\n mobileDropdown: \"=?\",\n });\n _this.transclude = true;\n _this.compile = function (element, atts) {\n if (atts.mobileDropdown == null)\n atts.mobileDropdown = \"true\";\n return _this.link;\n };\n _this.link = function (scope, element, atts, controllers) {\n _this.kbInputLinkFn(scope, element, atts, controllers, true, (function (val) { return false; }));\n var ngModel = controllers[0];\n var input = element.find(\"input\");\n scope._id = _tools.Utils.shortId();\n var toStringSafe = function (o) {\n if (o == null)\n return null;\n return o.toString();\n };\n var getItemValue = function (item) {\n if (item === null || item === undefined)\n return null;\n return scope.valueField ? item[scope.valueField] : item;\n };\n var getItemLabel = function (item) {\n var l;\n if (item != null) {\n if (scope.labelField && item[scope.labelField]) {\n l = item[scope.labelField];\n }\n else if (scope.valueField) {\n l = item[scope.valueField];\n }\n else {\n l = item;\n }\n }\n return toStringSafe(l);\n };\n var isEnabled = function () {\n return !scope.ngDisabled;\n };\n var setLabelForValue = function () {\n // if the labelField is being used, then we need to make a \n // call to the consumer to get the label for the value\n if (scope.labelField) {\n // first we try to find if we already have a match in our _matches to get the label from there\n // if not, then we make a call to the consumer to retrieve it\n var match = scope._matches ? scope._matches.find(function (m) { return getItemValue(m) == ngModel.$viewValue; }) : null;\n if (match) {\n scope._label = getItemLabel(match);\n }\n else {\n return $q.when(scope.getLabel({ value: ngModel.$viewValue })).then(function (l) {\n scope._label = l;\n });\n }\n }\n else { // no label-field is being used, so we just set the text input to the value\n scope._label = ngModel.$viewValue;\n }\n };\n ngModel.$render = function () {\n setLabelForValue();\n };\n scope._itemMousedown = function (e, item) {\n e.preventDefault(); // so we don't lose focus and trigger the blur event\n scope._select(item);\n // call submit for search boxes\n if (scope.submit)\n scope.submit({ item: item });\n };\n scope._select = function (item) {\n if (isEnabled()) {\n hideDropdown();\n ngModel.$setViewValue(getItemValue(item));\n scope._label = getItemLabel(item);\n scope._hint = null;\n $timeout(function () {\n suppressFocusEvent = true;\n input.focus();\n // suppressFocusEvent = false;\n }, 0);\n }\n };\n var showDropdown = function () {\n // scope._activeIndex = 0;\n scope._dropdownOpen = true;\n };\n var hideDropdown = function () {\n scope._dropdownOpen = false;\n };\n scope._isActive = function (index) {\n return index === scope._activeIndex;\n };\n var throttle = scope.throttle ? (scope.throttle == \"true\") : false;\n var getMatches = _tools.Utils.throttle(function () {\n if (isEnabled()) {\n var query = toStringSafe(scope._label);\n if (query && (!scope.minCharacters || query.length >= scope.minCharacters)) {\n scope._inProgress = true;\n return $q.when(scope.source({ query: query })).then(function (result) {\n scope._matches = result;\n if (scope._matches && scope._matches.length)\n showDropdown();\n scope._hint = null;\n if (scope._label) {\n // if the first match is an exact match so far, then show the hint\n if (scope._matches && scope._matches.length) {\n var o = scope._matches[0];\n var l = getItemLabel(o);\n if (l && l.toString().toLowerCase().startsWith(scope._label.toLowerCase())) {\n // match the case of whatever the user has already typed\n scope._hint = scope._label + l.substr(scope._label.length);\n }\n scope._activeIndex = 0;\n }\n else {\n scope._activeIndex = -1;\n }\n scope._activeIndex = scope.editable ? -1 : 0;\n }\n }).finally(function () {\n scope._inProgress = false;\n });\n }\n }\n }, throttle ? 300 : 0);\n var suppressFocusEvent = false;\n scope._focus = function (e) {\n if (!suppressFocusEvent && !scope._dropdownOpen) {\n getMatches();\n }\n suppressFocusEvent = false;\n };\n scope._blur = function (e) {\n // if this is editable, then set ngModel to whatever the user typed in when the input loses focus\n // also when a labelField is declared, it CAN'T be editable\n if (scope.editable) {\n ngModel.$setViewValue(scope._label);\n }\n else {\n setLabelForValue();\n }\n scope._hint = null;\n };\n scope._inputChange = function (e) {\n getMatches();\n };\n var buildItem = function (val) {\n var item = null;\n if (scope._activeIndex > -1) {\n item = scope._matches[scope._activeIndex];\n }\n else if (scope.valueField) {\n item = {};\n item[scope.valueField] = val;\n }\n else {\n item = val;\n }\n return item;\n };\n var moveUp = function () {\n if (scope._dropdownOpen) {\n // if we are already at index zero, then close the dropdown\n var newIndex = scope._activeIndex - 1;\n if (newIndex >= 0)\n scope._activeIndex = newIndex;\n }\n };\n var moveDown = function () {\n showDropdown();\n // if we are already at index zero, then close the dropdown\n var newIndex = scope._activeIndex + 1;\n if (newIndex < scope._matches.length)\n scope._activeIndex = newIndex;\n };\n // bind keyboard events: arrows up(38) / down(40), enter(13) and tab(9), esc(27)\n element.on(\"keydown\", function (e) {\n if (e.which == 38) {\n e.preventDefault();\n scope.$apply(function () {\n moveUp();\n });\n }\n if (e.which == 40) {\n e.preventDefault();\n scope.$apply(function () {\n moveDown();\n });\n }\n if (e.which == 9 || e.which == 13) {\n scope.$apply(function () {\n var item = buildItem(scope._label);\n if ((scope._dropdownOpen && scope._activeIndex > -1) || scope.editable) {\n scope._select(item);\n e.stopPropagation();\n }\n else {\n hideDropdown();\n scope._blur(null);\n }\n // call submit for search boxes \n if (scope.submit) {\n scope.submit({ item: item });\n }\n });\n }\n if (e.which == 27) {\n e.preventDefault();\n scope.$apply(function () {\n hideDropdown();\n e.stopPropagation();\n });\n }\n });\n scope.$on(\"$destroy\", function () {\n element.off();\n });\n };\n return _this;\n }\n KbAutoComplete = __decorate([\n NgComponent({\n token: Token.KbAutoComplete,\n dependencies: [\n Token.$Q,\n Token.$Http,\n Token.$Timeout,\n ]\n })\n ], KbAutoComplete);\n return KbAutoComplete;\n }(KbInput));\n\n var KbAvatarSelect = /** @class */ (function (_super) {\n __extends(KbAvatarSelect, _super);\n function KbAvatarSelect(kbService, $rootScope, uploadService, $filter, apiService) {\n var _this = _super.call(this) || this;\n _this.replace = true;\n _this.restrict = \"E\";\n _this.scope = {\n ngModel: \"=\",\n userId: \"=\"\n };\n _this.template = Dirs.component(\"kb-avatar-select\");\n _this.link = function (scope, element, atts, ngModelController) {\n scope.isEnabled = function () {\n return !($(element).hasClass(\"disabled\") || $(element).attr(\"disabled\"));\n };\n scope.imgPath = $filter(\"profileImage\")(scope.ngModel);\n scope.clear = function () {\n apiService.users.clearProfileImage(scope.userId).then(function (user) {\n scope.ngModel = user.imagePath;\n scope.imgPath = user.imagePath;\n if (scope.userId == $rootScope.user.id) {\n $rootScope.$broadcast(_tools.events.avatarChanged, scope.ngModel);\n }\n });\n };\n scope.click = function () {\n if (scope.isEnabled()) {\n uploadService.promptUserToChooseFile(\"image/*\").then(function (file) {\n uploadService.uploadProfileImage(file, scope.userId).then(function () {\n scope.ngModel = scope.userId.toString();\n scope.imgPath = $filter(\"profileImage\")(scope.ngModel);\n if (scope.userId == $rootScope.user.id) {\n $rootScope.$broadcast(_tools.events.avatarChanged, scope.ngModel);\n }\n });\n });\n }\n };\n };\n return _this;\n }\n KbAvatarSelect = __decorate([\n NgComponent({\n token: Token.KbAvatarSelect,\n dependencies: [\n Token.KbService,\n Token.$RootScope,\n Token.UploadService,\n Token.$Filter,\n Token.ApiService,\n ]\n })\n ], KbAvatarSelect);\n return KbAvatarSelect;\n }(Directive));\n\n var KbAvatar = /** @class */ (function (_super) {\n __extends(KbAvatar, _super);\n function KbAvatar($rootScope, dialogService, $http) {\n var _this = _super.call(this) || this;\n _this.$rootScope = $rootScope;\n _this.dialogService = dialogService;\n _this.$http = $http;\n _this.replace = true;\n _this.template = Dirs.component(\"kb-avatar\");\n _this.restrict = \"E\";\n _this.scope = {\n path: \"=\"\n };\n _this.link = function (scope, element, atts) {\n $rootScope.$on(_tools.events.avatarChanged, function (e, newPath) {\n // Adding a hash to force the model to change (otherwise the image will not\n // auto-load, assuming the newPath has not changed (but the data has)\n scope.path = newPath + \"#\" + (new Date()).getTime().toString();\n });\n };\n return _this;\n }\n KbAvatar = __decorate([\n NgComponent({\n token: Token.KbAvatar,\n dependencies: [\n Token.$RootScope,\n Token.DialogService,\n Token.$Http,\n ]\n })\n ], KbAvatar);\n return KbAvatar;\n }(Directive));\n\n var KbButton = /** @class */ (function (_super) {\n __extends(KbButton, _super);\n function KbButton($timeout) {\n var _this = _super.call(this) || this;\n _this.restrict = \"E\";\n _this.replace = true;\n _this.transclude = true;\n _this.scope = {\n ngClick: \"&\",\n textColor: \"=?\",\n backgroundColor: \"=?\"\n };\n _this.template = Dirs.component(\"kb-button\");\n return _this;\n }\n KbButton = __decorate([\n NgComponent({\n token: Token.KbButton\n })\n ], KbButton);\n return KbButton;\n }(Directive));\n\n /**\n * KbCheckbox\n *\n * pass in an inputId to explicitly set the checkbox input with an id,\n * otherwise if its in a kbfield will use a guid that was generated by the kbField\n * if there is no ngModel and no id provided, it will create it's own guid\n */\n var KbCheckbox = /** @class */ (function (_super) {\n __extends(KbCheckbox, _super);\n function KbCheckbox($timeout) {\n var _this = _super.call(this, $timeout) || this;\n _this.scope = _tools.Utils.extend(_this.scope, {\n inputId: \"=?\"\n });\n _this.template = Dirs.component(\"kb-checkbox\");\n _this.link = function (scope, element, atts, controllers) {\n _this.kbInputLinkFn(scope, element, atts, controllers);\n var ngModel = controllers[0];\n var kbField = controllers.length > 1 ? controllers[1] : null;\n if (atts.inputId) ;\n else if (kbField && atts.ngModel) {\n // if we're inside a kbfield, then tie the labels together with the same id \n scope.inputId = _tools.Utils.shortId();\n if (!scope.ignoreField) {\n kbField.scope.isCheckbox = true;\n kbField.scope._checkboxId = scope.inputId;\n }\n }\n else {\n scope.inputId = _tools.Utils.shortId();\n }\n if (!scope.inputId) {\n throw new Error(\"empty checkbox id\");\n }\n element.on(\"keydown\", function (e) {\n if (e.which == 13 || e.which == 32 && !scope.ngDisabled) {\n scope.$apply(function () {\n scope.ngModel = !scope.ngModel;\n scope.ngChange();\n });\n e.preventDefault();\n }\n else if (e.which == 27) {\n element.blur();\n }\n });\n scope.$on(\"$destroy\", function () {\n element.off();\n });\n };\n return _this;\n }\n KbCheckbox = __decorate([\n NgComponent({\n token: Token.KbCheckbox,\n dependencies: [\n Token.$Timeout\n ]\n })\n ], KbCheckbox);\n return KbCheckbox;\n }(KbInput));\n\n var KbColorPicker = /** @class */ (function (_super) {\n __extends(KbColorPicker, _super);\n function KbColorPicker($timeout) {\n var _this = _super.call(this) || this;\n _this.restrict = \"E\";\n _this.replace = true;\n _this.scope = {\n ngModel: \"=\"\n };\n _this.require = \"?ngModel\";\n _this.template = Dirs.component(\"kb-color-picker\");\n _this.link = function (scope, element, atts, ngModel) {\n element.minicolors({\n control: \"hue\",\n defaultValue: scope.ngModel || \"\",\n inline: false,\n letterCase: \"lowercase\",\n opacity: true,\n position: \"bottom left\",\n change: function (newValue) {\n scope.$apply(function () {\n ngModel.$setViewValue(newValue);\n });\n }\n });\n element.parent().addClass(\"kb-color-picker\");\n element.parent().append('
');\n ngModel.$render = function () {\n $timeout(function () {\n element.minicolors(\"value\", ngModel.$viewValue || \"\");\n }, 0, false);\n };\n scope.$on(\"$destroy\", function () {\n element.minicolors(\"destroy\");\n });\n };\n return _this;\n }\n KbColorPicker = __decorate([\n NgComponent({\n token: Token.KbColorPicker,\n dependencies: [\n Token.$Timeout\n ]\n })\n ], KbColorPicker);\n return KbColorPicker;\n }(Directive));\n\n var KbColumn = /** @class */ (function (_super) {\n __extends(KbColumn, _super);\n function KbColumn() {\n var _this = _super.call(this) || this;\n _this.require = [\"^?kbSearchGrid\", \"^?kbDataGrid\"];\n _this.replace = true;\n _this.template = Dirs.component(\"kb-column\");\n _this.restrict = \"AE\";\n _this.scope = {\n label: \"@\",\n id: \"@\",\n field: \"@\",\n sortable: \"=?\",\n toggleSort: \"&\",\n order: \"=?\"\n };\n _this.transclude = true;\n _this.link = function (scope, element, atts, gridCtrl) {\n if (scope.sortable == null)\n scope.sortable = true;\n gridCtrl = gridCtrl[0] ? gridCtrl[0] : gridCtrl[1];\n gridCtrl.addColumn(scope);\n scope.show = function () {\n return ((typeof (atts.kbIf) == \"undefined\") || scope.$parent.$eval(atts.kbIf) != false);\n };\n scope.getClass = function () {\n return element.attr(\"class\");\n };\n scope.getStyle = function () {\n return element.attr(\"style\");\n };\n };\n return _this;\n }\n KbColumn = __decorate([\n NgComponent({\n token: Token.KbColumn,\n dependencies: []\n })\n ], KbColumn);\n return KbColumn;\n }(Directive));\n\n var KbComments = /** @class */ (function (_super) {\n __extends(KbComments, _super);\n function KbComments($rootScope, dialogService, $http, authService) {\n var _this = _super.call(this) || this;\n _this.$rootScope = $rootScope;\n _this.dialogService = dialogService;\n _this.$http = $http;\n _this.authService = authService;\n _this.replace = false;\n _this.template = Dirs.component(\"kb-comments\");\n _this.restrict = \"E\";\n _this.scope = {\n objectId: \"=\",\n tableName: \"@\",\n api: \"=?\"\n };\n _this.link = function (scope, element, atts) {\n if (!angular.isDefined(scope.api)) {\n scope.api = {};\n }\n scope._comments = [];\n scope.api.refresh = function () {\n // get the comments for this object\n if (angular.isDefined(scope.objectId) && $rootScope.user.canViewComments) {\n _this.$http.get(\"/api/comments\", {\n params: {\n objectId: scope.objectId,\n tableName: scope.tableName\n }\n }).then(function (r) {\n scope._comments = r.data ? r.data : [];\n });\n }\n };\n scope.api.refresh();\n scope._delete = function (item) {\n scope._comments.remove(item);\n _this.$http.delete(\"/api/comments/\" + item.id);\n };\n scope._model = { text: \"\" };\n scope._cancel = function () {\n scope._model.text = \"\";\n };\n scope._addComment = function () {\n var newComment = {\n idUser: $rootScope.user.id,\n tableName: scope.tableName,\n body: scope._model.text,\n createdByName: $rootScope.user.firstName + \" \" + $rootScope.user.lastName,\n createdByImagePath: $rootScope.user.imagePath\n };\n _this.$http.post(\"/api/comments/\" + scope.objectId, newComment).then(function (r) {\n scope._comments.push(r.data);\n scope._model.text = \"\";\n });\n };\n scope._edit = function (item) {\n dialogService.input({\n msg: \"Comment Edit\",\n inputType: enums.eInputDialogType.textArea,\n value: item.body,\n buttons: [\n new enums.InputDialogButton(loc.ok, _tools.icons.success, function (args) {\n item.body = args.value;\n _this.$http.put(\"/api/comments/\" + item.id, item).then(function (r) {\n });\n }),\n new enums.InputDialogButton(loc.cancel, _tools.icons.cancel, function (args) {\n })\n ]\n });\n };\n };\n return _this;\n }\n KbComments = __decorate([\n NgComponent({\n token: Token.KbComments,\n dependencies: [\n Token.$RootScope,\n Token.DialogService,\n Token.$Http,\n Token.AuthService,\n ]\n })\n ], KbComments);\n return KbComments;\n }(Directive));\n\n var KbContent = /** @class */ (function (_super) {\n __extends(KbContent, _super);\n function KbContent() {\n var _this = _super.call(this) || this;\n _this.restrict = \"A\";\n _this.scope = false;\n _this.link = function (scope, element, atts) {\n element.addClass(\"ng-binding\").data(\"$binding\", atts.kbContent);\n scope.$watch(atts.kbContent, function (value) {\n element.html(value || \"\");\n });\n };\n return _this;\n }\n KbContent = __decorate([\n NgComponent({\n token: Token.KbContent\n })\n ], KbContent);\n return KbContent;\n }(Directive));\n\n var KbDataGrid = /** @class */ (function (_super) {\n __extends(KbDataGrid, _super);\n function KbDataGrid() {\n var _this = _super.call(this) || this;\n _this.replace = true;\n _this.template = Dirs.component(\"kb-data-grid\");\n _this.restrict = \"AE\";\n _this.scope = false;\n _this.transclude = true;\n _this.controller = [\"$scope\", \"$element\", function ($scope, $element) {\n var columns = $scope.columns = [];\n this.addColumn = function (column) {\n var exists = columns.some(function (c) { return c.id == column.id; });\n if (!exists) {\n columns.push(column);\n column.$on(\"$destroy\", function (event) {\n columns.remove(column);\n });\n }\n };\n }];\n _this.link = function (scope, element, atts) {\n scope.ngModel = scope.$eval(atts.ngModel);\n };\n return _this;\n }\n KbDataGrid = __decorate([\n NgComponent({\n token: Token.KbDataGrid,\n dependencies: []\n })\n ], KbDataGrid);\n return KbDataGrid;\n }(Directive));\n\n var KbDatePicker = /** @class */ (function (_super) {\n __extends(KbDatePicker, _super);\n function KbDatePicker($timeout) {\n var _this = _super.call(this, $timeout) || this;\n _this.template = Dirs.component(\"kb-date-picker\");\n _this.scope = _tools.Utils.extend(_this.scope, {\n minDate: \"=?\",\n maxDate: \"=?\",\n format: \"=?\",\n enableTime: \"=?\"\n });\n _this.link = function (scope, element, atts, controllers) {\n _this.kbInputLinkFn(scope, element, atts, controllers);\n var ngModel = controllers[0];\n var input = element.find(\"input\")[0];\n var picker = flatpickr__default['default'](input, {\n onChange: function () {\n ngModel.$setViewValue(picker.parseDate(input.value) || null);\n },\n enableTime: !!scope.enableTime\n });\n ngModel.$render = function () {\n picker.setDate(ngModel.$viewValue);\n };\n scope.$watch(\"minDate\", function (newValue, oldValue) {\n picker.set(\"minDate\", newValue);\n });\n scope.$watch(\"maxDate\", function (newValue, oldValue) {\n picker.set(\"maxDate\", newValue);\n });\n scope.$watch(\"format\", function (newValue, oldValue) {\n picker.set(\"dateFormat\", newValue || \"Y-m-d\");\n picker.setDate(ngModel.$viewValue, false); // set the date to update the format in the input\n });\n scope.$watch(\"enableTime\", function (newValue, oldValue) {\n picker.set(\"enableTime\", !!newValue);\n });\n scope._clear = function () {\n picker.clear();\n };\n scope.$on(\"$destroy\", function () {\n if (picker) {\n picker.destroy();\n }\n element.off();\n });\n };\n return _this;\n }\n KbDatePicker = __decorate([\n NgComponent({\n token: Token.KbDatePicker,\n dependencies: [\n Token.$Timeout\n ]\n })\n ], KbDatePicker);\n return KbDatePicker;\n }(KbInput));\n\n var KbDropdown = /** @class */ (function (_super) {\n __extends(KbDropdown, _super);\n function KbDropdown($timeout) {\n var _this = _super.call(this) || this;\n _this.restrict = \"EA\";\n _this.scope = {\n open: \"=\",\n scrollTo: \"@\",\n autoDirection: \"=\",\n horizontalAlign: \"@\",\n verticalAlign: \"@\",\n height: \"@\",\n width: \"@\",\n animate: \"@\",\n ignoreClickOn: \"@\",\n ignoreClickOnParent: \"@\"\n };\n _this.replace = true;\n _this.transclude = true;\n _this.template = \"\\n
\\n
\\n
\\n
\";\n _this.link = function (scope, element, atts) {\n var timeouts = [];\n var guid = _tools.Utils.shortId();\n var $parent = $(element).parent();\n var openIsDefined = angular.isDefined(atts.open);\n var hAlign = scope.horizontalAlign || \"left\";\n var vAlign = scope.verticalAlign || \"bottom\";\n var vAlignOpposite = vAlign == \"top\" ? \"bottom\" : \"top\";\n var isVisible = false;\n // if height is set, make the dropdown scrollable\n if (scope.height && scope.height != 'auto')\n element.addClass(\"kb-dropdown--scrollable\");\n var height = scope.height || \"auto\";\n element.css(\"max-height\", height);\n // define a tether\n var tether;\n var createTether = function () {\n if (!tether) {\n var options = {\n element: element,\n target: $parent,\n attachment: vAlignOpposite + \" \" + hAlign,\n targetAttachment: vAlign + \" \" + hAlign,\n constraints: [\n {\n to: document,\n attachment: \"together\",\n pin: [\"left\", \"right\"]\n }\n ],\n classes: {\n tether: false,\n element: false,\n target: false,\n enabled: false,\n // 'element-attached': false,\n // 'target-attached': false,\n // 'abutted': false\n }\n };\n // if the dropdown is part of a hotspot, and we are in XR, then we need to add to the hotspot div instead of body\n var p = element[0].closest(\".xr-overlay\");\n if (p) {\n options.bodyElement = p;\n }\n tether = new Tether__default['default'](options);\n }\n };\n var scrollToActive = function () {\n if (isVisible && scope.scrollTo && scope.scrollTo.length > 1) {\n var $item = element.find(scope.scrollTo);\n if ($item.length > 0) {\n _tools.Utils.scrollIntoView({ elem: $item[0], mode: _tools.eScrollMode.middleIfNecessary, animate: false });\n }\n }\n };\n scope.$watch(\"scrollTo\", function (newValue) {\n scrollToActive();\n });\n var preventScroll = function (e) {\n if (e.target == document.body)\n e.preventDefault();\n };\n var hideDropdown = function () {\n if (!isVisible)\n return;\n isVisible = false;\n //stage the close so CSS can animate it\n $parent.removeClass(\"is-open\");\n element.removeClass(\"is-open\");\n setTimeout(function () {\n element.css(\"display\", \"none\");\n }, 366);\n document.removeEventListener(\"click\", onDocumentClicked, true);\n document.body.removeEventListener(\"touchmove\", preventScroll);\n };\n // let hideDropdown = () => {\n // if (!isVisible) return;\n // isVisible = false;\n // // setting to false so that in configurators, we're not waiting for the dropdown \n // // to close while the scene is being updated.Makes it feel sluggish\n // // var animate = false; //!element.hasClass(\"tether-element-attached-bottom\");\n // let afterAnimation = () => {\n // element.css(\"display\", \"none\");\n // element.css(\"height\", \"auto\");\n // $parent.removeClass(\"is-open\");\n // };\n // if (scope.animate) {\n // element.animate({ height: 0 }, 133, \"easeOutSine\", afterAnimation);\n // } else {\n // afterAnimation();\n // // $timeout(afterAnimation, 0);\n // }\n // document.removeEventListener(\"click\", onDocumentClicked, true);\n // // $(\"body\").removeClass(\"is-mobile-keyboard\").css(\"overflow-y\", \"auto\");\n // document.body.removeEventListener(\"touchmove\", preventScroll);\n // };\n var onDocumentClicked = function (e) {\n var $target = $(e.target);\n if ($target.hasClass(\"kb-dropdown__overlay\")\n || (!$target.is(scope.ignoreClickOn) &&\n !$target.is($parent) &&\n !$.contains($parent[0], e.target) &&\n !$target.hasClass(\"kb-dropdown--ignore-click\") &&\n !$target.parents(\".kb-dropdown--ignore-click\").length &&\n (!scope.ignoreClickOnParent || !$target.parents(scope.ignoreClickOnParent).length))) {\n scope.$apply(function () {\n hideDropdown();\n if (openIsDefined) {\n scope.open = false;\n }\n });\n }\n };\n var showDropdown = function () {\n if (isVisible)\n return;\n isVisible = true;\n // Workaround for a bug in tether that finds a \"zero element\" in the xr-overlay when in the document.body context, which throws positioning off.\n var tetherZeroElem = document.body.querySelector(\".xr-overlay [data-tether-id]\");\n if (tetherZeroElem) {\n tetherZeroElem.parentElement.removeChild(tetherZeroElem);\n }\n createTether();\n var parentWidth = $parent[0].getBoundingClientRect().width;\n var maxWidth = scope.width == \"parent\" ? parentWidth : (scope.width || \"auto\");\n element.css(\"max-width\", maxWidth);\n // make the dropdown at least the width of the parent\n element.css(\"min-width\", $parent[0].getBoundingClientRect().width);\n element.css(\"display\", \"block\");\n tether.position();\n scrollToActive();\n $parent.addClass(\"is-open\");\n element.addClass(\"is-open\");\n document.addEventListener(\"click\", onDocumentClicked, true);\n $(document).on(\"touchmove\", preventScroll);\n $timeout(function () { return tether.position(); }, 0);\n };\n // let showDropdown = () => {\n // if (isVisible) return;\n // isVisible = true;\n // createTether();\n // // make the dropdown at least the width of the parent\n // element.css(\"min-width\", $parent[0].getBoundingClientRect().width);\n // $parent.addClass(\"is-open\");\n // element.css(\"display\", \"block\");\n // tether.position();\n // // element.css(\"height\", \"auto\");\n // let autoHeight = element.height();\n // // if we are attached to the bottom of the element, we don't want the\n // // normal height animation, so we just show the dropdown\n // let goingDown = !element.hasClass(\"tether-element-attached-bottom\");\n // let afterAnimation = () => {\n // element.css(\"height\", \"auto\");\n // document.addEventListener(\"click\", onDocumentClicked, true);\n // };\n // if (scope.animate && goingDown) {\n // scrollToActive();\n // element.height(0).animate({ height: autoHeight }, 133, \"easeOutSine\", afterAnimation);\n // } else { \n // timeouts.push($timeout(() => {\n // scrollToActive();\n // afterAnimation();\n // }, 0));\n // }\n // // $(\"body\").addClass(\"is-mobile-keyboard\").css(\"overflow-y\", \"hidden\");\n // $(document).on(\"touchmove\", preventScroll);\n // };\n var toggleDropdown = function (e) {\n if ($parent.hasClass(\"is-open\")) {\n hideDropdown();\n }\n else {\n showDropdown();\n }\n e.stopPropagation();\n };\n if (openIsDefined) {\n scope.$watch(\"open\", function (newValue) {\n if (newValue) {\n showDropdown();\n }\n else {\n hideDropdown();\n }\n });\n }\n else {\n $parent.on(\"click.kbdropdown\", toggleDropdown);\n }\n scope.$on(\"$destroy\", function () {\n timeouts.forEach(function (t) { return $timeout.cancel(t); });\n document.removeEventListener(\"click\", onDocumentClicked, true);\n $(document).off(\"touchmove\", preventScroll);\n $parent.off(\"click.kbdropdown\");\n // remove the dropdown element which is at the bottom of the body thanks to tether\n if (tether)\n tether.destroy();\n element.remove();\n });\n };\n return _this;\n }\n KbDropdown = __decorate([\n NgComponent({\n token: Token.KbDropdown,\n dependencies: [\n Token.$Timeout\n ]\n })\n ], KbDropdown);\n return KbDropdown;\n }(Directive));\n\n var KbEdit = /** @class */ (function (_super) {\n __extends(KbEdit, _super);\n function KbEdit($timeout) {\n var _this = _super.call(this) || this;\n _this.restrict = \"E\";\n _this.template = Dirs.component(\"kb-edit\");\n _this.scope = {\n ngModel: \"=\",\n enabled: \"=?\"\n };\n _this.replace = true;\n _this.link = function (scope, element, atts) {\n var input = $(element).find(\"input\");\n if (typeof scope.enabled == \"undefined\")\n scope.enabled = true;\n scope.$watch(\"enabled\", function (newValue) {\n if (!newValue) {\n scope._editing = false;\n input.hide();\n }\n });\n scope._click = function () {\n if (!scope.enabled)\n return;\n scope._editing = true;\n input.show();\n input.focus();\n };\n scope._blur = function () {\n scope._editing = false;\n input.hide();\n };\n scope._keydown = function ($event) {\n $event.stopPropagation();\n if ($event.keyCode == _tools.keyboard.enter) {\n scope._editing = false;\n input.hide();\n }\n };\n };\n return _this;\n }\n KbEdit = __decorate([\n NgComponent({\n token: Token.KbEdit,\n dependencies: [\n Token.$Timeout\n ]\n })\n ], KbEdit);\n return KbEdit;\n }(Directive));\n\n var KbEllipsis = /** @class */ (function (_super) {\n __extends(KbEllipsis, _super);\n function KbEllipsis(kbService) {\n var _this = _super.call(this) || this;\n _this.restrict = \"E\";\n _this.template = Dirs.component(\"kb-ellipsis\");\n _this.scope = false;\n _this.replace = true;\n return _this;\n // this.link = (scope, element, atts) => {\n // }\n }\n KbEllipsis = __decorate([\n NgComponent({\n token: Token.KbEllipsis,\n dependencies: [\n Token.KbService\n ]\n })\n ], KbEllipsis);\n return KbEllipsis;\n }(Directive));\n\n var KbExpanderGroup = /** @class */ (function (_super) {\n __extends(KbExpanderGroup, _super);\n function KbExpanderGroup() {\n var _this = _super.call(this) || this;\n _this.replace = false;\n _this.template = Dirs.component(\"kb-expander-group\");\n _this.restrict = \"E\";\n _this.scope = {\n accordion: \"=?\"\n };\n _this.transclude = true;\n // // add scope defaults to the compile function\n // this.compile = (element, atts: any) => {\n // if (!angular.isDefined(atts.accordion)) atts.selectable = \"true\";\n // if (!angular.isDefined(atts.expandable)) atts.expandable = \"true\";\n // };\n _this.controller = [\n \"$scope\",\n \"$element\",\n \"$attrs\",\n function ($scope, $element, $attrs) {\n // set the scope of the tree on it's controller so children can access it\n this.scope = $scope;\n $scope._expanders = [];\n // all child nodes register themselves with the tree to handle selection and accordion functionality\n this.registerExpander = function (e) {\n $scope._expanders.push(e);\n var off = e.$on(\"$destroy\", function (event) {\n $scope._expanders.remove(e);\n off();\n });\n if ($scope.accordion) {\n for (var _i = 0, _a = $scope._expanders; _i < _a.length; _i++) {\n var expander = _a[_i];\n if (expander.expanded) {\n updateExpanders(expander);\n return;\n }\n }\n }\n };\n this.expand = function (e) {\n if (e.expanded)\n updateExpanders(e);\n };\n var updateExpanders = function (activeExpander) {\n if ($scope.accordion) {\n for (var _i = 0, _a = $scope._expanders; _i < _a.length; _i++) {\n var e = _a[_i];\n if (e !== activeExpander)\n e.expanded = false;\n }\n }\n };\n }\n ];\n return _this;\n }\n KbExpanderGroup = __decorate([\n NgComponent({\n token: Token.KbExpanderGroup\n })\n ], KbExpanderGroup);\n return KbExpanderGroup;\n }(Directive));\n\n var KbExpander = /** @class */ (function (_super) {\n __extends(KbExpander, _super);\n function KbExpander($timeout) {\n var _this = _super.call(this) || this;\n _this.restrict = \"E\";\n _this.template = Dirs.component(\"kb-expander\");\n _this.transclude = {\n \"title\": \"?kbExpanderTitle\",\n \"body\": \"kbExpanderBody\"\n };\n _this.scope = {\n expanded: \"=?\",\n expandedChanged: \"&\",\n invalid: \"=?\",\n icon: \"@\",\n image: \"@\"\n };\n _this.replace = false;\n _this.require = \"?^^kbExpanderGroup\";\n _this.link = function (scope, element, atts, kbExpanderGroup) {\n if (kbExpanderGroup)\n kbExpanderGroup.registerExpander(scope);\n scope._toggle = function () {\n scope.expanded = !scope.expanded;\n };\n scope.$watch(\"expanded\", function (newVal, oldVal) {\n if (newVal != oldVal) {\n if (kbExpanderGroup && scope.expanded)\n kbExpanderGroup.expand(scope);\n if (scope.expandedChanged)\n scope.expandedChanged();\n }\n });\n };\n return _this;\n }\n KbExpander = __decorate([\n NgComponent({\n token: Token.KbExpander,\n dependencies: [\n Token.$Timeout\n ]\n })\n ], KbExpander);\n return KbExpander;\n }(Directive));\n\n /**\n * kbField\n * works in tandem with kbForm. Will pull the modelType from kbForm and use it to find localized label\n * and description for the field. It will also search it's direct children looking for an ngModel, as it\n * needs this info to find the model property name being bound to (also used to find the label and description)\n *\n * To override the localized label and description, you can directly set the attributes labelLoc and descLockb\n * to the name of a localization resource.\n *\n * If there is no clear way to find the ngModel child, you can set the modelProp attribute to help it find\n * the label and desc localizations\n *\n * The required attribute can be set to true to have a * show up at the end of the label\n *\n * If the model property is localizeable by the user, set the localize attribute to the model id\n * example: \n *\n *\n */\n var KbField = /** @class */ (function (_super) {\n __extends(KbField, _super);\n function KbField(kbService) {\n var _this = _super.call(this) || this;\n _this.restrict = \"EA\";\n _this.template = Dirs.component(\"kb-field\");\n _this.scope = {\n required: \"@\",\n label: \"@\",\n labelLoc: \"@\",\n desc: \"@\",\n descLoc: \"@\",\n ngDisabled: \"=?\",\n validationErrors: \"=?\",\n runFixThis: \"&\",\n warnings: \"=?\",\n fixOptions: \"=?\",\n isCheckbox: \"=?\",\n helpMedia: \"=?\",\n helpUrl: \"=?\",\n mobileHelpDropdown: \"=?\",\n useZeroPadding: \"=?\"\n };\n _this.replace = true;\n _this.transclude = true;\n _this.require = \"^?kbForm\";\n _this.compile = function (element, atts) {\n if (atts.mobileHelpDropdown == null)\n atts.mobileHelpDropdown = \"true\";\n return _this.link;\n };\n _this.controller = [\"$scope\", \"$element\", function ($scope, $element) {\n this.scope = $scope;\n this.setFocused = function (focused) {\n if ($scope._focused !== focused) {\n $element.toggleClass(\"kb-field--is-focused\", focused);\n }\n $scope._focused = focused;\n };\n this.setHasValue = function (hasValue) {\n if ($scope._hasValue !== hasValue) {\n $element.toggleClass(\"kb-field--has-value\", hasValue);\n }\n $scope._hasValue = hasValue;\n };\n this.setShouldFloat = function (shouldFloat) {\n $element.toggleClass(\"kb-field--should-float\", shouldFloat);\n };\n }];\n _this.link = function (scope, element, atts, kbForm) {\n if (kbForm) { //integration with kbForm\n var modelProp_1;\n //if in a kbForm, we look in the child input and \n // scrape the ng - model from it so we know the property we're connecting to\n var $input = element.find(\".kb-field__input *[ng-model]\").first();\n if ($input.length > 0) {\n var path = $input.attr(\"ng-model\");\n modelProp_1 = path.substring(path.lastIndexOf(\".\") + 1);\n }\n // if title is specified, then it means it's the name of a loc\n var autoLoc = false; // whether the label/desc is being automatically inferred\n if (modelProp_1 && !scope.labelLoc) {\n // title was not specified, so we look for a kbForm ancestor that could be providing\n // model type information\n if (kbForm && kbForm.scope.modelType && modelProp_1) {\n scope.labelLoc = kbForm.scope.modelType + \"_\" + modelProp_1 + \"_title\";\n scope.descLoc = kbForm.scope.modelType + \"_\" + modelProp_1 + \"_desc\";\n autoLoc = true;\n // check to see if the loc exists... if not, we can try generic resources\n if (!loc[scope.labelLoc.toLowerCase()]) {\n scope.labelLoc = \"generic_\" + modelProp_1 + \"_title\";\n scope.descLoc = \"generic_\" + modelProp_1 + \"_desc\";\n // if the generics don't exist either, then we'll just not have a label\n if (!loc[scope.labelLoc.toLowerCase()]) {\n scope.labelLoc = \"\";\n scope.descLoc = \"\";\n }\n }\n }\n }\n if (scope.labelLoc) {\n scope.label = kbService.loc(scope.labelLoc);\n }\n if (scope.descLoc) {\n var autoDesc = kbService.loc(scope.descLoc);\n scope.desc = (autoLoc && autoDesc == scope.descLoc) ? \"\" : autoDesc;\n }\n // validation\n // if the validationErrors attribute was set, then we use it\n // if not set, then we check for a parentForm's validation property that matches our ngmodel expression\n if (!atts.validationErrors) {\n scope.$watch(function () {\n if (!kbForm.scope.validation)\n return null;\n return kbForm.scope.validation[modelProp_1];\n }, function (newValue) {\n if (newValue) {\n scope.validationErrors = [newValue];\n }\n else {\n scope.validationErrors ? scope.validationErrors.clear() : scope.validationErrors = [];\n }\n });\n }\n }\n //pass throughs for field controls in a configurator\n scope._runFixThis = function (f) {\n return scope.runFixThis({ fix: f });\n };\n // $scope._upload = file => {\n // return $scope.upload({ file });\n // };\n // $scope._autoCompleteQuery = query => {\n // return $scope.autoCompleteQuery({ query, field: $scope.field });\n // };\n // $scope._autoCompleteGetLabel = value => {\n // return $scope.autoCompleteGetLabel({ value, field: $scope.field });\n // };\n // $scope._translateKbo = property => {\n // return $scope.translateKbo({ kbObject: $scope.field, property });\n // };\n scope.$on(\"$destroy\", function () {\n });\n };\n return _this;\n }\n KbField = __decorate([\n NgComponent({\n token: Token.KbField,\n dependencies: [\n Token.KbService\n ]\n })\n ], KbField);\n return KbField;\n }(Directive));\n\n var KbFocus = /** @class */ (function (_super) {\n __extends(KbFocus, _super);\n function KbFocus($timeout) {\n var _this = _super.call(this) || this;\n _this.replace = true;\n _this.restrict = \"A\";\n _this.scope = false;\n _this.link = function (scope, element, atts) {\n $timeout(function () {\n element[0].focus();\n }, 200);\n };\n return _this;\n }\n KbFocus = __decorate([\n NgComponent({\n token: Token.KbFocus,\n dependencies: [\n Token.$Timeout\n ]\n })\n ], KbFocus);\n return KbFocus;\n }(Directive));\n\n var KbForm = /** @class */ (function (_super) {\n __extends(KbForm, _super);\n function KbForm() {\n var _this = _super.call(this) || this;\n _this.replace = true;\n _this.template = Dirs.component(\"kb-form\");\n _this.restrict = \"E\";\n _this.scope = {\n modelType: \"@\",\n validation: \"=\",\n ngDisabled: \"=?\"\n };\n _this.transclude = true;\n _this.controller = [\"$scope\", \"$element\", function ($scope, $element) {\n this.scope = $scope;\n }];\n return _this;\n }\n KbForm = __decorate([\n NgComponent({\n token: Token.KbForm,\n dependencies: []\n })\n ], KbForm);\n return KbForm;\n }(Directive));\n\n var KbIcon = /** @class */ (function (_super) {\n __extends(KbIcon, _super);\n function KbIcon(kbService) {\n var _this = _super.call(this) || this;\n _this.kbService = kbService;\n _this.restrict = \"E\";\n _this.template = Dirs.component(\"kb-icon\");\n _this.scope = {\n icon: \"@\",\n label: \"@\"\n };\n _this.replace = true;\n return _this;\n }\n KbIcon = __decorate([\n NgComponent({\n token: Token.KbIcon,\n dependencies: [\n Token.KbService\n ]\n })\n ], KbIcon);\n return KbIcon;\n }(Directive));\n\n /**\n * A performance driven directive that does the following:\n * * will not render the html it is placed on until the kb-if evaluates to truthy (like ng-if)\n * * will NOT destroy the html when kb-if thereafter evaluates to false. Instead, it will\n * hide the html like ng-show would, but also suspend all the watchers on this element and any children.\n *\n * Uses the feature described here: https://github.com/angular/angular.js/pull/16308\n */\n var KbIf = /** @class */ (function (_super) {\n __extends(KbIf, _super);\n function KbIf($animate) {\n var _this = _super.call(this) || this;\n _this.watchAtt = \"kbIf\";\n _this.restrict = \"A\";\n _this.priority = 600;\n _this.transclude = \"element\";\n _this.terminal = true;\n _this.$$tlb = true;\n _this.link = function (scope, element, atts, ctrl, $transclude) {\n var innerScope;\n var innerElement;\n var hide = function () {\n $animate.addClass(innerElement, \"ng-hide\", {\n tempClasses: \"ng-hide-animate\"\n });\n };\n var show = function () {\n $animate.removeClass(innerElement, \"ng-hide\", {\n tempClasses: \"ng-hide-animate\"\n });\n };\n scope.$watch(atts[_this.watchAtt], function (value, oVal) {\n // $animate[value ? 'removeClass' : 'addClass'](innerElement, NG_HIDE_CLASS, {\n // tempClasses: NG_HIDE_IN_PROGRESS_CLASS\n // });\n if (value) {\n if (!innerElement) {\n // Add the transcluded content after the transclusion comment placeholder \n $transclude(function (el, sc) {\n element.after(el);\n innerElement = el;\n innerScope = sc;\n innerScope.$resume();\n $animate.enter(el, element.parent(), element);\n innerElement.removeClass(\"ng-hide\");\n });\n }\n else {\n innerScope.$resume();\n show();\n }\n }\n else {\n if (innerElement) {\n if (_this.hideDelay) {\n setTimeout(function () {\n hide();\n }, _this.hideDelay);\n }\n else {\n hide();\n }\n // Before suspending, the scope should digest one more time to allow updates (e.g. initial watch)\n scope.$$postDigest(function () {\n innerScope.$suspend();\n });\n }\n }\n });\n };\n return _this;\n }\n KbIf = __decorate([\n NgComponent({\n token: Token.KbIf,\n dependencies: [\n Token.$Animate\n ]\n })\n ], KbIf);\n return KbIf;\n }(Directive));\n\n /**\n * A version of kbIf that delays the adding of the ng-hide once the value resolves to false to\n * give animations a chance to finish.\n */\n var KbIfDelay = /** @class */ (function (_super) {\n __extends(KbIfDelay, _super);\n function KbIfDelay($animate) {\n var _this = _super.call(this, $animate) || this;\n _this.watchAtt = \"kbIfDelay\";\n _this.hideDelay = 300;\n return _this;\n }\n KbIfDelay = __decorate([\n NgComponent({\n token: Token.KbIfDelay,\n dependencies: [\n Token.$Animate\n ]\n })\n ], KbIfDelay);\n return KbIfDelay;\n }(KbIf));\n\n var KbMultiSelect = /** @class */ (function (_super) {\n __extends(KbMultiSelect, _super);\n function KbMultiSelect($timeout, $window) {\n var _this = _super.call(this, $timeout) || this;\n _this.template = Dirs.component(\"kb-multi-select\");\n _this.scope = _tools.Utils.extend(_this.scope, {\n source: \"=\",\n valueField: \"@\",\n labelField: \"@\",\n headerTemplate: \"@\",\n data: \"=?\",\n addItem: \"&\",\n removeItem: \"&\",\n mode: \"@\",\n itemStyle: \"=?\",\n allowDeleteInHeader: \"=?\",\n itemIsSelectable: \"&\",\n mobileDropdown: \"=?\"\n });\n _this.transclude = true;\n _this.compile = function (element, atts) {\n if (angular.isUndefined(atts.mode)) {\n atts.mode = \"objects\";\n }\n if (angular.isUndefined(atts.allowDeleteInHeader)) {\n atts.allowDeleteInHeader = \"true\";\n }\n if (atts.mobileDropdown == null)\n atts.mobileDropdown = \"true\";\n return _this.link;\n };\n _this.link = function (s, e, a, c) { return _this.kbMultiSelectLinkFn(s, e, a, c, true); };\n return _this;\n }\n KbMultiSelect.prototype.kbMultiSelectLinkFn = function (scope, element, atts, controllers, shouldFloat) {\n if (shouldFloat === void 0) { shouldFloat = true; }\n this.kbInputLinkFn(scope, element, atts, controllers, shouldFloat);\n var ngModelCtrl = controllers[0];\n scope._dropdownOpen = false;\n scope._selectedItems = [];\n scope._selectedMap = [];\n scope._binding = { query: \"\" };\n var input = element.find(\"input\");\n scope._id = _tools.Utils.shortId();\n scope._isEnabled = function () {\n return !scope.ngDisabled;\n };\n var getItemValue = function (item) {\n if (item == null)\n return null;\n return scope.valueField ? item[scope.valueField] : item;\n };\n scope._getItemLabel = function (item) {\n if (scope.labelField && item[scope.labelField]) {\n return item[scope.labelField];\n }\n else if (scope.valueField) {\n return item[scope.valueField];\n }\n else {\n return item;\n }\n };\n var updateSelected = function () {\n scope._selectedItems.clear();\n // set all options to visible\n scope._selectedMap.clear();\n if (scope.source)\n scope.source.forEach(function (item) { return scope._selectedMap.push(false); });\n if (ngModelCtrl.$viewValue) {\n for (var _i = 0, _a = ngModelCtrl.$viewValue; _i < _a.length; _i++) {\n var item = _a[_i];\n var itemValue = item;\n if (scope.mode == \"objects\") {\n itemValue = getItemValue(item);\n }\n if (scope.source) {\n for (var i = 0; i < scope.source.length; i++) {\n var sourceItem = scope.source[i];\n if (getItemValue(sourceItem) == itemValue) {\n scope._selectedItems.push(sourceItem);\n // hide the option since it's selected\n scope._selectedMap[i] = true;\n break;\n }\n }\n }\n }\n }\n };\n // let showDropdown = () => {\n // scope._dropdownOpen = true;\n // // on mobile the filter input will kick off the keyboard, which we don't necessarily want. \n // // The problem is worse on IOS because of focus restrictions\n // if ($window.innerWidth >= Utils.MOBILE_WIDTH && !Utils.isIos()) {\n // $timeout(() => input.focus());\n // }\n // };\n // let hideDropdown = () => {\n // scope._dropdownOpen = false;\n // scope._binding.query = null;\n // updateFilteredSource();\n // };\n // let toggleDropdown = () => {\n // scope._dropdownOpen ? hideDropdown() : showDropdown();\n // };\n // options might be added after the ngModel is set by the consumer, so\n // we need to refind the selected option \n scope.$watchCollection(\"source\", function () {\n updateSelected();\n updateFilteredSource();\n });\n scope.$watchCollection(\"ngModel\", function () {\n // ngModel watches by reference, which doesn't work well for arrays\n updateSelected();\n });\n ngModelCtrl.$render = function () {\n updateSelected();\n };\n scope._itemMousedown = function (e) {\n e.preventDefault(); // so we don't lose focus\n };\n scope._itemClick = function (e, item) {\n e.preventDefault();\n scope._select(item);\n };\n scope._itemIsSelectable = function (item) {\n if (atts.itemIsSelectable) {\n return scope.itemIsSelectable({ item: item });\n }\n return true;\n };\n scope._select = function (sourceItem) {\n if (scope._isEnabled() && scope._itemIsSelectable(sourceItem)) {\n if (atts.addItem) {\n scope.addItem({ sourceItem: sourceItem });\n }\n else {\n if (isSelected(sourceItem)) {\n scope._delete(sourceItem);\n }\n else {\n var viewValue = ngModelCtrl.$viewValue;\n if (scope.mode == \"objects\") {\n ngModelCtrl.$setViewValue(viewValue.concat([sourceItem])); // $viewValue.push(sourceItem);\n }\n else {\n ngModelCtrl.$setViewValue(viewValue.concat([getItemValue(sourceItem)]));\n }\n }\n }\n //updateSelected(); don't need to call because the watch on ngModel picks up the change\n //scope.ngChange();\n // moveDown();\n }\n };\n scope._isActive = function (index) {\n return index === scope._activeIndex;\n };\n var updateFilteredSource = function () {\n if (!scope._binding.query) {\n scope._filteredSource = scope.source;\n }\n else {\n scope._filteredSource = _tools.SearchUtils.search(scope._binding.query, scope.source, function (o) { return scope._getItemLabel(o); }, 10000);\n scope._activeIndex = -1;\n }\n };\n scope._queryChange = function (e) {\n updateFilteredSource();\n };\n scope._queryKeydown = function (e) {\n if (e.which == 38) {\n moveUp();\n e.stopPropagation();\n }\n if (e.which == 40) {\n moveDown();\n e.stopPropagation();\n }\n if (e.which === 13) {\n enter();\n e.stopPropagation();\n }\n if (e.which === 9) {\n tab();\n if (scope._dropdownOpen) {\n e.stopPropagation();\n e.preventDefault();\n }\n }\n };\n scope._click = function (e) {\n if (scope._isEnabled()) {\n scope._activeIndex = -1;\n scope._dropdownOpen = !scope._dropdownOpen;\n }\n };\n scope._itemDeleteBtnClick = function (e, item) {\n scope._delete(item);\n e.stopPropagation();\n };\n scope._delete = function (item) {\n if (scope._isEnabled()) {\n if (atts.removeItem) {\n scope.removeItem({ item: item });\n }\n else {\n var itemValue = getItemValue(item);\n // the normal array.remove compares values strictly (with ===), \n // but we need == in this case because of possible string / number mismatch\n for (var i = ngModelCtrl.$viewValue.length - 1; i >= 0; i--) {\n var ngModelValue = ngModelCtrl.$viewValue[i];\n if (scope.mode == \"objects\") {\n ngModelValue = getItemValue(ngModelValue);\n }\n if (ngModelValue == itemValue) {\n var viewValue = ngModelCtrl.$viewValue;\n var newVal = __spreadArray([], viewValue, true);\n newVal.splice(i, 1);\n ngModelCtrl.$setViewValue(newVal);\n break;\n }\n }\n }\n //updateSelected(); don't need to call because the watch on ngModel picks up the change\n // scope.ngChange();\n }\n };\n var isSelected = function (sourceItem) {\n var optionVal = getItemValue(sourceItem);\n for (var _i = 0, _a = scope._selectedItems; _i < _a.length; _i++) {\n var selectedItem = _a[_i];\n if (optionVal === getItemValue(selectedItem)) {\n return true;\n }\n }\n return false;\n };\n var moveUp = function () {\n if (scope._dropdownOpen) {\n var newIndex = scope._activeIndex - 1;\n if (newIndex >= 0) {\n scope._activeIndex = newIndex;\n }\n }\n };\n var moveDown = function () {\n scope._dropdownOpen = true;\n var newIndex = scope._activeIndex + 1;\n if (newIndex < scope._filteredSource.length) {\n scope._activeIndex = newIndex;\n }\n };\n var enter = function () {\n if (scope._dropdownOpen) {\n if (scope._filteredSource.length && scope._activeIndex > -1) {\n scope._select(scope.source[scope._activeIndex]);\n }\n }\n else {\n scope._dropdownOpen = true;\n }\n };\n var tab = function () {\n if (scope._dropdownOpen) {\n if (scope._filteredSource.length && scope._activeIndex > -1) {\n scope._select(scope.source[scope._activeIndex]);\n scope._dropdownOpen = false;\n }\n }\n };\n // bind keyboard events: arrows up(38) / down(40), enter(13) and tab(9), esc(27)\n element.on(\"keydown\", function (e) {\n if (e.key == 'ArrowUp') {\n e.preventDefault();\n scope.$apply(function () {\n moveUp();\n });\n }\n if (e.key == 'ArrowDown') {\n e.preventDefault();\n scope.$apply(function () {\n moveDown();\n });\n }\n if (e.key == 'Enter') {\n scope.$apply(function () {\n e.preventDefault();\n enter();\n });\n }\n if (e.key == 'Tab') {\n scope.$apply(function () {\n if (scope._dropdownOpen) {\n e.stopPropagation();\n e.preventDefault();\n }\n tab();\n });\n }\n if (e.key == 'Escape') {\n e.preventDefault();\n element.trigger('blur');\n scope.$apply(function () {\n scope._dropdownOpen = false;\n e.stopPropagation();\n });\n }\n });\n scope.$on(\"$destroy\", function () {\n element.off();\n });\n };\n KbMultiSelect = __decorate([\n NgComponent({\n token: Token.KbMultiSelect,\n dependencies: [\n Token.$Timeout,\n Token.$Window,\n ]\n })\n ], KbMultiSelect);\n return KbMultiSelect;\n }(KbInput));\n\n var ImageSelectHelper = /** @class */ (function () {\n function ImageSelectHelper($window, $timeout, scope, element) {\n this.$window = $window;\n this.$timeout = $timeout;\n this.scope = scope;\n this.element = element;\n var windowResize = _tools.Utils.debounce(function () {\n //if we are in a mode of scroll, then we need to find a margin between items that leaves an option\n //halfway out of view to be clear there are more items to scroll horizontally to.\n if (scope.optionLayout == enums.eOptionLayout.scroll) {\n //make sure there are enough items to scroll\n var minMargin = 4;\n var play = .05;\n var minPlayRange = .5 - play;\n var maxPlayRange = .5 + play;\n var $items = element.find(\".kb-option\");\n var $firstItem = $items.length ? $items[0] : null;\n if ($firstItem) {\n var itemWidth = $firstItem.offsetWidth;\n var itemAndMargin = itemWidth + minMargin;\n var elWidth = element.innerWidth();\n //make sure there are enough items that we should be scrolling\n if (elWidth < (itemAndMargin * $items.length)) {\n //find the number of visible items with min margin\n var n = elWidth / itemAndMargin;\n //now round up to the nearest half\n var remainder = n % 1;\n if (remainder < minPlayRange || remainder > maxPlayRange) {\n var nModifier = remainder < minPlayRange ? -remainder - .5 : .5 - remainder;\n var idealN = n + nModifier;\n var idealMargin = (elWidth - (itemWidth * idealN)) / (idealN - .5);\n $items.css(\"margin-right\", idealMargin);\n }\n else {\n //do nothing... we are close enough\n $items.css(\"margin-right\", minMargin);\n }\n }\n }\n }\n }, 100);\n $($window).on(\"resize\", windowResize);\n $timeout(function () {\n windowResize();\n }, 0);\n scope.$watch(\"optionLayout\", function (newVal, oldVal) {\n element.removeClass(\"kb-image-select--\" + (oldVal || enums.eOptionLayout.wrap));\n element.addClass(\"kb-image-select--\" + (newVal || enums.eOptionLayout.wrap));\n windowResize();\n });\n scope.$on(\"$destroy\", function () {\n element.off();\n $($window).off(\"resize\", windowResize);\n });\n }\n return ImageSelectHelper;\n }());\n\n var KbImageMultiSelect = /** @class */ (function (_super) {\n __extends(KbImageMultiSelect, _super);\n function KbImageMultiSelect($timeout, $window) {\n var _this = _super.call(this, $timeout, $window) || this;\n _this.scope = _tools.Utils.extend(_this.scope, {\n optionLayout: \"=?\"\n });\n _this.template = Dirs.component(\"kb-image-multi-select\");\n _this.link = function (scope, element, atts, controllers) {\n _this.kbMultiSelectLinkFn(scope, element, atts, controllers, false);\n var helper = new ImageSelectHelper($window, $timeout, scope, element);\n };\n return _this;\n }\n KbImageMultiSelect = __decorate([\n NgComponent({\n token: Token.KbImageMultiSelect,\n dependencies: [\n Token.$Timeout,\n Token.$Window,\n ]\n })\n ], KbImageMultiSelect);\n return KbImageMultiSelect;\n }(KbMultiSelect));\n\n var KbImageSelect = /** @class */ (function (_super) {\n __extends(KbImageSelect, _super);\n function KbImageSelect($timeout, $window) {\n var _this = _super.call(this, $timeout) || this;\n _this.template = Dirs.component(\"kb-image-select\");\n _this.scope = _tools.Utils.extend(_this.scope, {\n source: \"=\",\n data: \"=?\",\n valueField: \"@\",\n labelField: \"@\",\n itemStyle: \"=?\",\n optionLayout: \"=?\"\n });\n _this.transclude = true;\n _this.link = function (scope, element, atts, controllers) {\n _this.kbInputLinkFn(scope, element, atts, controllers, false);\n var helper = new ImageSelectHelper($window, $timeout, scope, element);\n var ngModel = controllers[0];\n var getItemValue = function (item) {\n if (item === null || item === undefined)\n return null;\n return scope.valueField ? item[scope.valueField] : item;\n };\n var isEnabled = function () {\n return !scope.ngDisabled;\n };\n var updateSelected = function () {\n var selected = null;\n if (scope.source) {\n for (var _i = 0, _a = scope.source; _i < _a.length; _i++) {\n var item = _a[_i];\n item.$selected = false;\n if (getItemValue(item) == ngModel.$viewValue) {\n selected = item;\n item.$selected = true;\n }\n }\n }\n scope._selectedItem = selected;\n };\n // options might be added after the ngModel is set by the consumer, so\n // we need to refind the selected option \n scope.$watchCollection(\"source\", function () {\n updateSelected();\n });\n ngModel.$render = function () {\n updateSelected();\n };\n scope._select = function (item) {\n if (isEnabled()) {\n ngModel.$setViewValue(getItemValue(item));\n scope._selectedItem = item;\n for (var _i = 0, _a = scope.source; _i < _a.length; _i++) {\n var item_1 = _a[_i];\n item_1.$selected = false;\n }\n item.$selected = true;\n }\n };\n scope._helpClick = function (e) {\n e.stopPropagation();\n };\n var moveUp = function () {\n if (scope.source && scope._selectedItem) {\n var curIndex = scope.source.indexOf(scope._selectedItem);\n var newIndex = curIndex - 1;\n if (newIndex >= 0)\n scope._select(scope.source[newIndex]);\n }\n else if (scope.source && scope.source.length) {\n scope._select(scope.source[0]);\n }\n };\n var moveDown = function () {\n if (scope.source && scope._selectedItem) {\n var curIndex = scope.source.indexOf(scope._selectedItem);\n var newIndex = curIndex + 1;\n if (newIndex < scope.source.length)\n scope._select(scope.source[newIndex]);\n }\n else if (scope.source && scope.source.length) {\n scope._select(scope.source[0]);\n }\n };\n var scrollSelectedIntoView = function () {\n if (scope.optionLayout == enums.eOptionLayout.scroll) {\n $timeout(function () {\n var $selected = element.find(\".kb-option.selected\");\n var selectedElem = $selected.length ? $selected[0] : null;\n if (selectedElem) {\n _tools.Utils.scrollIntoView({\n elem: selectedElem,\n mode: _tools.eScrollMode.nearest,\n horizontal: true,\n animate: true,\n nearestEndPadding: parseInt(selectedElem.style.marginRight) + selectedElem.offsetWidth / 2\n });\n }\n });\n }\n };\n scope.$watch(\"_selectedItem\", function () {\n scrollSelectedIntoView();\n });\n // bind keyboard events: arrows up(38) / down(40), enter(13) and tab(9), esc(27)\n element.on(\"keydown\", function (e) {\n if (e.key == 'ArrowLeft' || e.key == 'ArrowUp') {\n e.preventDefault();\n scope.$apply(function () {\n moveUp();\n });\n }\n if (e.key == 'ArrowRight' || e.key == 'ArrowDown') {\n e.preventDefault();\n scope.$apply(function () {\n moveDown();\n });\n }\n if (e.key == 'Escape') {\n element.trigger('blur');\n }\n });\n scope.$on(\"$destroy\", function () {\n element.off();\n // $($window).off(\"resize\", windowResize);\n });\n };\n return _this;\n }\n KbImageSelect = __decorate([\n NgComponent({\n token: Token.KbImageSelect,\n dependencies: [\n Token.$Timeout,\n Token.$Window\n ]\n })\n ], KbImageSelect);\n return KbImageSelect;\n }(KbInput));\n\n /**\n * Creates a new scope for ng-include along with being able to set variables on the new scope\n */\n var KbInclude = /** @class */ (function (_super) {\n __extends(KbInclude, _super);\n function KbInclude($templateRequest, $compile) {\n var _this = _super.call(this) || this;\n _this.restrict = \"A\";\n _this.link = function (scope, element, atts) {\n var templateUrl = scope.$eval(atts.kbInclude);\n $templateRequest(templateUrl, true).then(function (response) {\n var $template = angular.element(response);\n // compile the template\n var compiled = $compile($template);\n // append it to the label\n element.replaceWith($template);\n // now link it to the parent scope(we don't want this scope because it's an isolate scope)\n compiled(scope);\n });\n };\n return _this;\n }\n KbInclude = __decorate([\n NgComponent({\n token: Token.KbInclude,\n dependencies: [\n Token.$TemplateRequest,\n Token.$Compile\n ]\n })\n ], KbInclude);\n return KbInclude;\n }(Directive));\n\n var KbInfiniteScroll = /** @class */ (function (_super) {\n __extends(KbInfiniteScroll, _super);\n function KbInfiniteScroll($rootScope, $window, $timeout, $compile, promiseTracker, $q) {\n var _this = _super.call(this) || this;\n _this.$rootScope = $rootScope;\n _this.restrict = \"A\";\n _this.replace = false;\n _this.scope = false;\n _this.link = function (scope, element, atts) {\n // var checkWhenEnabled: boolean;\n var scrollDistance;\n // var scrollEnabled: boolean;\n var window = angular.element($window);\n var $parent;\n var $child;\n if (angular.isDefined(atts.kbInfiniteScrollParent)) {\n $parent = angular.element(atts.kbInfiniteScrollParent);\n //if we are inside a directive, then the element might not be in the DOM yet,\n //so we search for it in the directive element chain\n if (!$parent.length) {\n $parent = _this.findDirectiveElement(element, atts.kbInfiniteScrollParent);\n }\n }\n else {\n $parent = $window;\n }\n if (angular.isDefined(atts.kbInfiniteScrollChild)) {\n $child = angular.element(atts.kbInfiniteScrollChild);\n //if we are inside a directive, then the element might not be in the DOM yet,\n //so we search for it in the directive element chain\n if (!$child.length) {\n $child = _this.findDirectiveElement(element, atts.kbInfiniteScrollChild);\n }\n }\n else {\n $child = element;\n }\n var isHorizontal = false;\n if (angular.isDefined(atts.kbInfiniteScrollOrientation)) {\n if (atts.kbInfiniteScrollOrientation.toLowerCase() == \"horizontal\") {\n isHorizontal = true;\n }\n }\n var template;\n if (isHorizontal) {\n template = \"\\n
\\n
\";\n }\n else {\n template = \"\\n
\\n
\";\n }\n var $template = $(template);\n var spinner = \"\";\n $template.append(spinner);\n $template = $compile($template)(scope);\n element.append($template);\n scrollDistance = 0;\n if (atts.kbInfiniteScrollDistance) {\n scope.$watch(atts.kbInfiniteScrollDistance, function (value) {\n return scrollDistance = parseFloat(value);\n });\n }\n var busy = false;\n var handler = _tools.Utils.debounce(function () {\n if (busy)\n return;\n busy = true;\n var shouldScroll = false;\n if (isHorizontal) {\n var parentWidth = $parent[0].clientWidth;\n var portalRight = parentWidth + $parent[0].scrollLeft;\n var remaining = $child[0].clientWidth - portalRight;\n shouldScroll = remaining <= parentWidth * scrollDistance;\n }\n else {\n var parentHeight = $parent[0].clientHeight;\n var portalBottom = parentHeight + $parent[0].scrollTop;\n var remaining = $child[0].clientHeight - portalBottom;\n shouldScroll = remaining <= parentHeight * scrollDistance;\n }\n return $q.when(shouldScroll && scope.$eval(atts.kbInfiniteScroll)).then(function () {\n busy = false;\n });\n }, 10);\n var onMousewheel = function (e) {\n if (e.deltaY === 1) {\n e.preventDefault();\n }\n };\n $parent[0].addEventListener(\"scroll\", handler);\n $parent[0].addEventListener(\"mousewheel\", onMousewheel); //need the mousewheel event for a bug in chrome: https://stackoverflow.com/a/47684257/709968\n //$parent.on(\"scroll\", handler);\n scope.$on(\"$destroy\", function () {\n $parent[0].removeEventListener(\"scroll\", handler);\n $parent[0].removeEventListener(\"mousewheel\", onMousewheel);\n //return $parent.off(\"scroll\", handler);\n });\n return $timeout((function () {\n if (atts.kbInfiniteScrollImmediateCheck) {\n if (scope.$eval(atts.kbInfiniteScrollImmediateCheck)) {\n return handler();\n }\n }\n else {\n return handler();\n }\n }), 0);\n };\n return _this;\n }\n KbInfiniteScroll.prototype.findDirectiveElement = function (directiveElement, selector) {\n //if we are inside a directive, then the element might not be in the DOM yet,\n //so we search for it in the directive element chain\n var p = directiveElement;\n while (p.parent().length) {\n p = p.parent();\n }\n return p.find(selector).addBack(selector);\n };\n KbInfiniteScroll = __decorate([\n NgComponent({\n token: Token.KbInfiniteScroll,\n dependencies: [\n Token.$RootScope,\n Token.$Window,\n Token.$Timeout,\n Token.$Compile,\n Token.PromiseTracker,\n Token.$Q,\n ]\n })\n ], KbInfiniteScroll);\n return KbInfiniteScroll;\n }(Directive));\n\n var KbLabel = /** @class */ (function (_super) {\n __extends(KbLabel, _super);\n function KbLabel() {\n var _this = _super.call(this) || this;\n _this.replace = true;\n _this.template = Dirs.component(\"kb-label\");\n _this.restrict = \"E\";\n _this.scope = {\n invalid: \"=?\",\n icon: \"@\",\n image: \"@\",\n imageWhenSelected: \"@\",\n selected: \"=?\",\n backgroundColor: \"=?\",\n textColor: \"=?\"\n };\n _this.transclude = true;\n _this.link = function (scope, element, atts) {\n };\n return _this;\n }\n KbLabel = __decorate([\n NgComponent({\n token: Token.KbLabel\n })\n ], KbLabel);\n return KbLabel;\n }(Directive));\n\n var KbListItem = /** @class */ (function (_super) {\n __extends(KbListItem, _super);\n function KbListItem($timeout) {\n var _this = _super.call(this) || this;\n _this.require = \"^kbList\";\n _this.replace = true;\n _this.template = Dirs.component(\"kb-list-item\");\n _this.restrict = \"AE\";\n _this.scope = {\n selectable: \"=?\",\n item: \"=?\",\n image: \"@\",\n icon: \"@\",\n onDelete: \"&\",\n onDoubleClick: \"&\",\n deletable: \"=?\",\n childTemplate: \"@\"\n };\n _this.transclude = true;\n _this.controller = [\n \"$scope\",\n \"$element\",\n \"$attrs\",\n \"$transclude\",\n \"$templateCache\",\n Token.$Compile.key,\n Token.$Http.key,\n function ($scope, $element, $attrs, $transclude, $templateCache, $compile, $http) {\n this.scope = $scope;\n var processTemplateElement = function ($template) {\n // compile the template\n var compiled = $compile($template, $transclude);\n // append it to the label\n $element.html(\"\").append($template);\n // now link it to the parent scope(we don't want this scope because it's an isolate scope)\n compiled($scope.$parent);\n };\n // if a child template was provided, then use that instead of the transclusion content\n var templateName = $scope.childTemplate;\n var $template = angular.element($templateCache.get(templateName));\n if (!$template.length) {\n $http.get(templateName).then(function (response) {\n $templateCache.put(templateName, response.data);\n $template = angular.element(response.data);\n processTemplateElement($template);\n });\n }\n else {\n processTemplateElement($template);\n }\n }\n ];\n _this.compile = function (element, atts) {\n if (angular.isUndefined(atts.selectable)) {\n atts.selectable = \"true\";\n }\n if (angular.isUndefined(atts.deletable)) {\n atts.deletable = \"true\";\n }\n return _this.link;\n };\n _this.link = function (scope, element, atts, listController) {\n // get parent scopes to use for selection and expansion\n var listScope = listController.scope;\n scope._listScope = listScope;\n // register the item with the parent kbList\n listController.registerListItem(scope);\n scope._itemClick = function (e) {\n // select the item if it's selectable\n if (listScope.selectable && scope.selectable) {\n // set the selected item on the tree so it can be bound to by controllers\n // if (listScope.multiple && e.)\n var mouseEvent = e;\n if (listScope.multiple) {\n if (mouseEvent.ctrlKey) {\n listScope.addToSelectedItems(scope.item);\n }\n else if (mouseEvent.shiftKey) {\n listScope.shiftToSelectedItems(scope.item);\n }\n else {\n listScope.setSelectedItems(scope.item);\n }\n }\n else {\n listScope.selectedItem = scope.item;\n }\n }\n };\n scope._itemDoubleClick = function (e) {\n scope.onDoubleClick();\n };\n };\n return _this;\n }\n KbListItem = __decorate([\n NgComponent({\n token: Token.KbListItem,\n dependencies: [\n Token.$Timeout,\n ]\n })\n ], KbListItem);\n return KbListItem;\n }(Directive));\n\n /**\n * kbList\n *\n * to use kbList, you nest kb-list-item directives inside of a kb-list directive:\n * \n * \n * \n *\n */\n var KbList = /** @class */ (function (_super) {\n __extends(KbList, _super);\n function KbList() {\n var _this = _super.call(this) || this;\n _this.replace = true;\n _this.template = Dirs.component(\"kb-list\");\n _this.restrict = \"AE\";\n _this.scope = {\n selectedItem: \"=\",\n selectedItems: \"=?\",\n skin: \"@\",\n multiple: \"=?\",\n selectable: \"=?\"\n };\n _this.transclude = true;\n // add scope defaults to the compile function\n _this.compile = function (element, atts) {\n if (angular.isUndefined(atts.selectable)) {\n atts.selectable = \"true\";\n }\n };\n _this.controller = [\n \"$scope\",\n \"$element\",\n \"$attrs\",\n \"$transclude\",\n function ($scope, $element, $attrs, $transclude) {\n // set the scope of the tree on it's controller so children can access it\n this.scope = $scope;\n $scope._listItems = [];\n $scope.isSelected = function ($id) {\n if ($scope.multiple) {\n return ($scope._selectedListItems.some(function (li) { return li.$id == $id; }));\n }\n return ($scope._selectedListItem ? $scope._selectedListItem.$id == $id : false);\n };\n var lastSelectedItem = -1;\n $scope.addToSelectedItems = function (item, doNotAutoRemove) {\n if (!doNotAutoRemove && $scope.selectedItems.indexOf(item) > -1) {\n $scope.selectedItems.remove(item);\n return;\n }\n $scope.selectedItems.push(item);\n lastSelectedItem = $scope._listItems.map(function (i) { return i.item; }).indexOf(item);\n };\n $scope.setSelectedItems = function (item) {\n $scope.selectedItems.clear();\n $scope.selectedItems.push(item);\n lastSelectedItem = $scope._listItems.map(function (i) { return i.item; }).indexOf(item);\n };\n $scope.shiftToSelectedItems = function (item) {\n if (lastSelectedItem < 0) {\n $scope.setSelectedItems(item);\n }\n var newIdx = $scope._listItems.map(function (i) { return i.item; }).indexOf(item);\n var i = (newIdx > lastSelectedItem ? lastSelectedItem + 1 : lastSelectedItem - 1);\n var check = function () {\n if (newIdx > lastSelectedItem)\n return i <= newIdx;\n return i >= newIdx;\n };\n var increment = function () {\n if (newIdx > lastSelectedItem)\n i++;\n else\n i--;\n };\n for (; check(); increment()) {\n $scope.addToSelectedItems($scope._listItems[i].item, true);\n }\n lastSelectedItem = newIdx;\n };\n // all child nodes register themselves with the tree to handle selection and accordion functionality\n this.registerListItem = function (listItem) {\n $scope._listItems.push(listItem);\n listItem.$on(\"$destroy\", function (event) {\n $scope._listItems.remove(listItem);\n });\n };\n var selectFirstItem = function () {\n if ($scope._listItems.length) {\n if ($scope.multiple) {\n $scope._selectedListItems = [$scope._listItems.first()];\n $scope.selectedItems = [$scope._selectedListItems.first().item];\n }\n else {\n $scope._selectedListItem = $scope._listItems.first();\n $scope.selectedItem = $scope._selectedListItem.item;\n }\n }\n };\n var updateSelectedItem = function () {\n $scope._selectedListItems = [];\n $scope._selectedListItem = undefined;\n if ((!$scope.multiple && !$scope.selectedItem) ||\n ($scope.multiple && (!$scope.selectedItems ||\n !$scope.selectedItems.length))) {\n selectFirstItem();\n }\n else {\n for (var _i = 0, _a = $scope._listItems; _i < _a.length; _i++) {\n var listItem = _a[_i];\n if (!$scope.multiple && $scope.selectedItem == listItem.item) {\n $scope._selectedListItem = listItem;\n }\n else if ($scope.multiple && $scope.selectedItems.indexOf(listItem.item) > -1) {\n $scope._selectedListItems.push(listItem);\n }\n }\n // if listitem is still undefined, the selected item is no longer in the list, so we reset it\n if ($scope.multiple && !$scope._selectedListItems.length) {\n $scope.selectedItems = [];\n }\n else if (!$scope.multiple && !$scope._selectedListItem) {\n $scope.selectedItem = undefined;\n }\n }\n };\n // if the consumer changes the selected item, we update the selected node\n if ($scope.multiple) {\n $scope.$watchCollection(\"selectedItems\", function () {\n updateSelectedItem();\n });\n }\n else {\n $scope.$watch(\"selectedItem\", function () {\n updateSelectedItem();\n });\n }\n // nodes might be added after the selectedItem is set by the consumer, so\n // we need to refind the selected node when the nodes collection changes\n $scope.$watchCollection(\"_listItems\", function () {\n // if (!$scope._selectedListItem) {\n updateSelectedItem();\n // }\n });\n }\n ];\n return _this;\n }\n KbList = __decorate([\n NgComponent({\n token: Token.KbList,\n dependencies: []\n })\n ], KbList);\n return KbList;\n }(Directive));\n\n /**\n * Given markdown text in the ngModel, will display the html\n */\n var KbMarkdownViewer = /** @class */ (function (_super) {\n __extends(KbMarkdownViewer, _super);\n function KbMarkdownViewer() {\n var _this = _super.call(this) || this;\n _this.scope = {\n ngModel: \"=\"\n };\n _this.restrict = \"E\";\n _this.template = Dirs.component(\"kb-markdown-viewer\", exports.eBundle.app);\n _this.replace = true;\n _this.require = \"ngModel\";\n _this.link = function (scope, element, atts, ngModel) {\n // override the onPrepareImage from the markdown library so that we can have our\n // custom image size add-on. \n // to control size of images, append =heightxwidth to the end of the url\n // some markdown implementations have a space before the equals sign, but\n // that doesn't seem to be possible here because markdownDeep won't recognize it\n // as an image at all\n MarkdownDeep.Markdown.prototype.OnPrepareImage = function (tag) {\n var re = /=(\\w+)x(\\w+)$/;\n var src = tag.attributes[\"src\"];\n var parts = src.match(re);\n if (parts && parts[0]) {\n tag.attributes[\"src\"] = src.substr(0, src.length - parts[0].length);\n tag.attributes[\"width\"] = parts[1];\n tag.attributes[\"height\"] = parts[2];\n }\n };\n ngModel.$render = function () {\n // Create an instance of Markdown\n var md = new MarkdownDeep.Markdown();\n md.NewWindowForExternalLinks = true;\n var v = ngModel.$viewValue;\n scope._html = v ? md.Transform(v) : null;\n };\n };\n return _this;\n }\n KbMarkdownViewer = __decorate([\n NgComponent({\n token: Token.KbMarkdownViewer\n })\n ], KbMarkdownViewer);\n return KbMarkdownViewer;\n }(Directive));\n\n var KbMax = /** @class */ (function (_super) {\n __extends(KbMax, _super);\n function KbMax() {\n var _this = _super.call(this) || this;\n _this.restrict = \"A\";\n _this.require = \"ngModel\";\n _this.link = function (scope, elem, attr, ctrl) {\n var maxValidator = function (value) {\n var max = scope.$eval(attr.ngMax) || Infinity;\n if (ctrl.$viewValue && ctrl.$viewValue > max) {\n $(elem).val(max);\n return max;\n }\n return value;\n };\n ctrl.$parsers.push(maxValidator);\n ctrl.$formatters.push(maxValidator);\n };\n return _this;\n }\n KbMax = __decorate([\n NgComponent({\n token: Token.KbMax,\n dependencies: []\n })\n ], KbMax);\n return KbMax;\n }(Directive));\n\n var KbMediaList = /** @class */ (function (_super) {\n __extends(KbMediaList, _super);\n function KbMediaList($rootScope, dialogService) {\n var _this = _super.call(this) || this;\n _this.$rootScope = $rootScope;\n _this.dialogService = dialogService;\n _this.replace = true;\n // this.require = 'ngModel';\n _this.template = Dirs.component(\"kb-media-list\");\n _this.restrict = \"E\";\n _this.scope = {\n ngModel: \"=\",\n addItem: \"&\",\n imagePath: \"@\"\n };\n _this.link = function (scope, element, atts) {\n scope.isEnabled = function () {\n return !($(element).hasClass(\"disabled\") || $(element).attr(\"disabled\"));\n };\n scope.options = {\n start: function (e, ui) {\n $(e.target).data(\"ui-sortable\").floating = true;\n },\n tolerance: \"pointer\"\n };\n // element.sortable({\n // items: \"li:not(#btn-add-image)\",\n // tolerance: \"pointer\"\n // });\n scope.deleteItem = function (index) {\n scope.ngModel.splice(index, 1);\n };\n };\n return _this;\n }\n KbMediaList = __decorate([\n NgComponent({\n token: Token.KbMediaList,\n dependencies: [\n Token.$RootScope,\n Token.DialogService,\n ]\n })\n ], KbMediaList);\n return KbMediaList;\n }(Directive));\n\n var KbMediaManager = /** @class */ (function (_super) {\n __extends(KbMediaManager, _super);\n function KbMediaManager($window, $http, kbService, dialogService, $rootScope, drawerService, uploadService, $q, $filter, $timeout) {\n var _this = _super.call(this) || this;\n _this.$window = $window;\n _this.$http = $http;\n _this.kbService = kbService;\n _this.dialogService = dialogService;\n _this.$rootScope = $rootScope;\n _this.drawerService = drawerService;\n _this.uploadService = uploadService;\n _this.$q = $q;\n _this.$filter = $filter;\n _this.$timeout = $timeout;\n _this.getChildren = function (dir) {\n var params = $.param($.extend({ dir: dir }, { filter: _this.atts.filter }));\n var url = _this.mscope.apiPath + \"/children?\" + params;\n _this.$http.get(url, { tracker: _this.mscope.tracker }).then(function (r) {\n _this.mscope.files = r.data;\n _this.$timeout(function () {\n if (_this.mscope.startPath) {\n var startFile = _this.mscope.files.find(function (f) { return f.relativePath == _this.mscope.startPath; });\n if (startFile)\n _this.mscope.selectedFile = startFile;\n _this.mscope.startPath = null;\n }\n }, 0);\n });\n };\n _this.getDirectory = function (path) {\n var index = path.indexOf(\"/\");\n if (index > -1) {\n return path.substr(0, index);\n }\n return \"\";\n };\n _this.restrict = \"E\";\n _this.template = Dirs.component(\"kb-media-manager\");\n _this.scope = {\n dialog: \"@\",\n multiple: \"=?\",\n selectedFile: \"=?\",\n selectedFiles: \"=?\",\n filter: \"@\",\n apiPath: \"@\",\n rootDir: \"@\",\n startPath: \"@\",\n open: \"&\",\n tracker: \"=?\"\n };\n _this.replace = true;\n _this.link = function (scope, element, atts) {\n _this.atts = atts;\n _this.mscope = scope;\n if (!_this.mscope.apiPath)\n _this.mscope.apiPath = \"api/media\";\n if (!_this.mscope.rootDir)\n _this.mscope.rootDir = \"media\";\n if (typeof atts.multiple == \"undefined\") {\n scope.multiple = true;\n }\n scope.isDialog = (atts.dialog == \"true\");\n scope.isReadOnly = !_this.$rootScope.user.canModifyMedia || _this.$rootScope.environment != \"dev\";\n scope.deleteItems = function () {\n _this.deleteSelectedListItems();\n };\n scope.refresh = function () {\n _this.refreshList();\n };\n scope.rename = function () {\n _this.rename();\n };\n scope.addFolder = function () {\n _this.addFolder();\n };\n scope.fileDoubleClicked = function (file) {\n // if this is a folder, then navigate to the folder. If a file, then call the handler of the consumer\n if (!file.isFile) {\n _this.navigate(file.relativePath);\n }\n else {\n if (scope.open) {\n scope.open({ file: file }); // call the handler of the consumer\n }\n }\n };\n scope.upload = function (accept) {\n _this.uploadService.promptUserToChooseFiles().then(function (files) {\n _this.onUpload({\n files: files\n });\n // setTimeout(() =>\n // {\n var promises = [];\n files.forEach(function (file) {\n var p = _this.uploadService.uploadFileToMedia(file, _this.currentDir, _this.mscope.apiPath);\n promises.push(p.then(function () {\n _this.uploadProgress({\n files: [file],\n percentComplete: 100\n });\n }, function () {\n _this.uploadError({\n files: [file]\n });\n }, function (e) {\n _this.uploadProgress({\n files: [file],\n percentComplete: ((e.loaded / e.total) * 100)\n });\n }));\n });\n _this.$q.all(promises).finally(function () { return _this.uploadComplete(); });\n // }, 500);\n });\n };\n scope.crumbClick = function (crumb) {\n _this.navigate(crumb.url);\n };\n scope.addBlank = function (ext) {\n _this.dialogService.input({\n msg: \"Select a name for the new file\",\n inputType: \"text\",\n value: \"New File\",\n buttons: [\n new enums.InputDialogButton(loc.ok, _tools.icons.success, function (args) {\n if (args.value) {\n $http.post(\"/api/templates/blank\", {\n relativePath: _this.currentDir + args.value + \".\" + ext\n }, { tracker: scope.tracker }).then(function (response) {\n _this.refreshList();\n });\n }\n }),\n new enums.InputDialogButton(loc.cancel, _tools.icons.cancel, function (args) {\n })\n ]\n });\n };\n scope.files = [];\n if (!scope.isDialog) {\n if ($rootScope.user.canModifyMedia && _this.$rootScope.environment == \"dev\") {\n var drAddFolder = drawerService.addDrawer(_tools.icons.addFolder, loc.addfolder, scope.addFolder);\n }\n var drOpen = drawerService.addDrawer(_tools.icons.open, loc.open, function () { return scope.fileDoubleClicked(_this.selectedItem()); });\n if ($rootScope.user.canModifyMedia && _this.$rootScope.environment == \"dev\") {\n var drUpload = drawerService.addDrawer(_tools.icons.upload, loc.upload, scope.upload);\n var drDelete = drawerService.addDrawer(_tools.icons.deleter, loc.deleter, scope.deleteItems);\n var drRename = drawerService.addDrawer(_tools.icons.rename, loc.rename, scope.rename);\n }\n var drRefresh = drawerService.addDrawer(_tools.icons.refresh, loc.refresh, scope.refresh);\n }\n // setup root crumb\n var startDir = scope.startPath ? _this.getDirectory(scope.startPath) : \"\";\n _this.navigate(startDir);\n };\n return _this;\n }\n KbMediaManager.prototype.navigate = function (dir) {\n this.currentDir = dir;\n this.refreshCrumbs(dir);\n this.getChildren(dir);\n // this.mscope.listSource.read({ id: dir }); \n };\n KbMediaManager.prototype.refreshCrumbs = function (dir) {\n this.mscope.crumbs = [];\n this.mscope.crumbs.push({ url: \"\", name: this.mscope.rootDir, icon: _tools.icons.image });\n var segments = dir.split(\"/\");\n for (var index = 0; index < segments.length; index++) {\n var segment = segments[index];\n if (segment) {\n // calculate the absolute url of the segment\n var url = \"\";\n for (var i = 0; i <= index; i++) {\n url += segments[i] + \"/\";\n }\n this.mscope.crumbs.push({ url: url, name: segment, icon: _tools.icons.crumb });\n }\n }\n };\n KbMediaManager.prototype.deleteSelectedListItems = function () {\n var _this = this;\n this.dialogService.dialog({\n content: loc.msg_deletemedia,\n buttons: [\n new enums.DialogButton(loc.ok, _tools.icons.success, function () {\n var ids = new Array();\n var selected = _this.getListViewSelectedItems();\n selected.forEach(function (mobject) {\n _this.$http.delete(_this.mscope.apiPath, {\n params: {\n relativePath: mobject.relativePath\n },\n headers: {\n \"Content-Type\": \"application/json\"\n }\n });\n });\n // delete the stuff directly in the source so the user doesn't have to wait\n $.each(selected, function (index, mobject) {\n // now remove the item from the listview\n _this.mscope.files.remove(mobject);\n // (this.mscope.listSource).remove(mobject);\n });\n }),\n new enums.DialogButton(loc.cancel, _tools.icons.cancel, function (args) {\n })\n ]\n });\n };\n KbMediaManager.prototype.rename = function () {\n var _this = this;\n var selectedItems = this.getListViewSelectedItems();\n if (selectedItems && selectedItems.length > 0) {\n var item_1 = selectedItems[0];\n var msg = item_1.isFile ? loc.msg_renamefile : loc.msg_renamefolder;\n this.dialogService.input({\n msg: msg,\n value: item_1.name,\n buttons: [\n new enums.InputDialogButton(loc.ok, _tools.icons.success, function (args) {\n _this.$http.post(_this.mscope.apiPath + \"/rename\", {\n relativePath: item_1.relativePath, newName: args.value\n }, { tracker: _this.mscope.tracker })\n .then(function () {\n _this.refreshList();\n }, function (e) {\n _this.dialogService.alert({\n msg: \"Rename failed. Please ensure your filename does not contains slashes.\",\n type: enums.eAlertType.error\n });\n });\n }),\n new enums.InputDialogButton(loc.cancel, _tools.icons.cancel, function (args) {\n })\n ]\n });\n }\n };\n KbMediaManager.prototype.addFolder = function () {\n var _this = this;\n this.dialogService.input({\n msg: loc.msg_renamefolder,\n value: loc.newfolder,\n buttons: [\n new enums.InputDialogButton(loc.ok, _tools.icons.success, function (args) {\n _this.$http.post(_this.mscope.apiPath + \"/addfolder\", {\n dir: _this.currentDir, folderName: args.value\n }, { tracker: _this.mscope.tracker })\n .then(function () {\n _this.refreshList();\n });\n }),\n new enums.InputDialogButton(loc.cancel, _tools.icons.cancel, function (args) {\n })\n ]\n });\n };\n KbMediaManager.prototype.getListViewDataItem = function ($domItem) {\n var index = $domItem.index();\n return null;\n // return this.mscope.listSource.view()[index];\n };\n KbMediaManager.prototype.getListViewSelectedItems = function () {\n if (this.mscope.multiple) {\n return this.mscope.selectedFiles;\n }\n return [this.mscope.selectedFile];\n };\n KbMediaManager.prototype.selectedItem = function () {\n var selected = this.getListViewSelectedItems();\n if (selected) {\n return selected[0];\n }\n return null;\n };\n KbMediaManager.prototype.refreshList = function () {\n this.getChildren(this.currentDir);\n };\n KbMediaManager.prototype.onUpload = function (e) {\n var _this = this;\n if (!this.mscope.uploadingFiles)\n this.mscope.uploadingFiles = [];\n angular.forEach(e.files, function (item, index) {\n item.percentComplete = 0;\n _this.mscope.uploadingFiles.push(item);\n });\n if (!this.mscope.uploading) {\n this.uploadDialog = this.dialogService.dialog({\n template: Dirs.view(\"dialog-upload-files\"),\n scope: this.mscope.$new(),\n buttons: [\n new enums.InputDialogButton(loc.ok, _tools.icons.success, function (args) {\n _this.mscope.uploadingFiles = null;\n _this.refreshList();\n }, false) // hide the ok button by passing in visible = false\n ]\n });\n }\n this.mscope.uploading = true;\n };\n KbMediaManager.prototype.uploadProgress = function (e) {\n var _this = this;\n $.each(e.files, function (index, file) {\n var $li = $(\"#uploading-list #\" + _this.$filter(\"fileId\")(file.name));\n file.percentComplete = e.percentComplete;\n });\n };\n KbMediaManager.prototype.uploadError = function (e) {\n var _this = this;\n $.each(e.files, function (index, file) {\n var $li = $(\"#uploading-list #\" + _this.$filter(\"fileId\")(file.name));\n $li.prepend('
' + _tools.icons.error + \"
\");\n });\n };\n KbMediaManager.prototype.uploadComplete = function (e) {\n this.mscope.uploading = false;\n // show the buttons in the dialog now\\\n this.uploadDialog.buttons[0].visible = true;\n };\n KbMediaManager = __decorate([\n NgComponent({\n token: Token.KbMediaManager,\n dependencies: [\n Token.$Window,\n Token.$Http,\n Token.KbService,\n Token.DialogService,\n Token.$RootScope,\n Token.DrawerService,\n Token.UploadService,\n Token.$Q,\n Token.$Filter,\n Token.$Timeout,\n ]\n })\n ], KbMediaManager);\n return KbMediaManager;\n }(Directive));\n\n var KbMediaSelect = /** @class */ (function (_super) {\n __extends(KbMediaSelect, _super);\n function KbMediaSelect(kbService, $rootScope, dialogService) {\n var _this = _super.call(this) || this;\n _this.replace = true;\n _this.restrict = \"E\";\n _this.scope = {\n ngModel: \"=\"\n };\n _this.template = Dirs.component(\"kb-media-select\");\n _this.link = function (scope, element, atts, ngModelController) {\n scope.isEnabled = function () {\n return !($(element).hasClass(\"disabled\") || $(element).attr(\"disabled\"));\n };\n scope.clear = function () {\n scope.ngModel = null;\n };\n scope.click = function () {\n if (scope.isEnabled()) {\n dialogService.mediaSelect({\n startPath: scope.ngModel,\n buttons: [\n new enums.MediaDialogButton(loc.ok, _tools.icons.success, function (args) {\n scope.ngModel = args.selectedItem ? args.selectedItem.relativePath : null;\n }),\n new enums.MediaDialogButton(loc.cancel, _tools.icons.cancel, function (args) {\n })\n ]\n });\n }\n };\n };\n return _this;\n }\n KbMediaSelect = __decorate([\n NgComponent({\n token: Token.KbMediaSelect,\n dependencies: [\n Token.KbService,\n Token.$RootScope,\n Token.DialogService,\n ]\n })\n ], KbMediaSelect);\n return KbMediaSelect;\n }(Directive));\n\n var KbMediaViewer = /** @class */ (function (_super) {\n __extends(KbMediaViewer, _super);\n function KbMediaViewer($filter, kbService, $sce, $rootScope, storageService) {\n var _this = _super.call(this) || this;\n _this.replace = true;\n _this.restrict = \"EA\";\n _this.template = Dirs.component(\"kb-media-viewer\");\n _this.scope = {\n path: \"=\",\n thumb: \"@\",\n cachebuster: \"=?\"\n };\n _this.link = function (scope, element, atts) {\n //// for some reason the classes aren't getting merged\n //// but it is shown correctly in atts. Here's a workaround\n // element.removeClass();\n // element.addClass(atts.class);\n scope.fallback = storageService.getFallbackImage();\n scope.$watch(\"path\", function (newValue) {\n scope.ext = kbService.getExtension(scope.path);\n if (scope.ext == \"ogv\")\n scope.ext = \"ogg\";\n if (_tools.extensions.image.indexOf(scope.ext) != -1) {\n scope.type = \"image\";\n if (scope.thumb) {\n scope.fullPath = $filter(\"thumb\")(scope.path);\n }\n else {\n scope.fullPath = $filter(\"media\")(scope.path);\n }\n }\n else if (_tools.extensions.video.indexOf(scope.ext) != -1) {\n scope.type = \"video\";\n scope.fullPath = $filter(\"media\")(scope.path);\n }\n if (_tools.Utils.isAbsoluteUrl(scope.path)) {\n scope.fullPath = scope.path;\n }\n if (scope.cachebuster) {\n scope.fullPath = scope.fullPath + \"?v=\" + $rootScope.cacheBuster;\n }\n scope.fullPath = $sce.trustAsResourceUrl(scope.fullPath);\n });\n };\n return _this;\n }\n KbMediaViewer = __decorate([\n NgComponent({\n token: Token.KbMediaViewer,\n dependencies: [\n Token.$Filter,\n Token.KbService,\n Token.$Sce,\n Token.$RootScope,\n Token.StorageService\n ]\n })\n ], KbMediaViewer);\n return KbMediaViewer;\n }(Directive));\n\n var KbMenuItem = /** @class */ (function (_super) {\n __extends(KbMenuItem, _super);\n function KbMenuItem(kbService, $state, $rootScope) {\n var _this = _super.call(this) || this;\n _this.kbService = kbService;\n _this.restrict = \"E\";\n _this.template = Dirs.component(\"kb-menu-item\");\n _this.scope = {\n icon: \"@\",\n label: \"@\",\n params: \"=?\"\n };\n _this.replace = true;\n _this.transclude = true;\n _this.link = function (scope, element, atts) {\n // remove the submenu element if there are no sub menu items\n var $subMenu = element.find(\".kb-menu__sub\");\n if (!$subMenu.html().length) {\n $subMenu.remove();\n }\n element.click(function () {\n var isExpanded = $(element).hasClass(\"is-expanded\");\n $(element).children(\".kb-menu__item\").removeClass(\"is-expanded\");\n if (!isExpanded) {\n $(element).addClass(\"is-expanded\");\n var collapse_1 = function () {\n $(element).removeClass(\"is-expanded\");\n $(\"html\").unbind(\"click\", collapse_1);\n };\n setTimeout(function () { $(\"html\").bind(\"click\", collapse_1); }, 1);\n }\n });\n scope.$on(\"$destroy\", function () {\n element.off();\n });\n };\n return _this;\n }\n KbMenuItem = __decorate([\n NgComponent({\n token: Token.KbMenuItem,\n dependencies: [\n Token.KbService,\n Token.$State,\n Token.$RootScope,\n ]\n })\n ], KbMenuItem);\n return KbMenuItem;\n }(Directive));\n\n var KbMenu = /** @class */ (function (_super) {\n __extends(KbMenu, _super);\n function KbMenu(kbService, $rootScope, $state) {\n var _this = _super.call(this) || this;\n _this.kbService = kbService;\n _this.restrict = \"E\";\n _this.template = Dirs.component(\"kb-menu\");\n _this.scope = true;\n _this.replace = true;\n _this.transclude = true;\n _this.link = function (scope, element, atts) {\n };\n return _this;\n }\n KbMenu = __decorate([\n NgComponent({\n token: Token.KbMenu,\n dependencies: [\n Token.KbService,\n Token.$RootScope,\n Token.$State,\n ]\n })\n ], KbMenu);\n return KbMenu;\n }(Directive));\n\n var KbMin = /** @class */ (function (_super) {\n __extends(KbMin, _super);\n function KbMin() {\n var _this = _super.call(this) || this;\n _this.restrict = \"A\";\n _this.require = \"ngModel\";\n _this.link = function (scope, elem, attr, ctrl) {\n var minValidator = function (value) {\n var min = scope.$eval(attr.ngMin) || 0;\n if (ctrl.$viewValue && ctrl.$viewValue < min) {\n $(elem).val(min);\n return min;\n }\n return value;\n };\n ctrl.$parsers.push(minValidator);\n ctrl.$formatters.push(minValidator);\n };\n return _this;\n }\n KbMin = __decorate([\n NgComponent({\n token: Token.KbMin,\n dependencies: []\n })\n ], KbMin);\n return KbMin;\n }(Directive));\n\n var KbMoney = /** @class */ (function (_super) {\n __extends(KbMoney, _super);\n function KbMoney(kbService, $rootScope) {\n var _this = _super.call(this) || this;\n _this.kbService = kbService;\n _this.$rootScope = $rootScope;\n _this.template = '';\n _this.restrict = \"E\";\n _this.scope = {\n label: \"@\",\n ngModel: \"=\",\n currency: \"@\"\n };\n _this.require = \"?ngModel\";\n _this.replace = true;\n _this.transclude = true;\n _this.link = function (scope, element, atts, ngModel) {\n var update = function (v) {\n return v ?\n kbService.fxConvert(parseFloat(v), _this.$rootScope.companySettings.currency.toUpperCase(), scope.currency)\n : 0;\n };\n scope.$watch(\"currency\", function () {\n ngModel.$modelValue = (update(ngModel.$viewValue));\n });\n ngModel.$formatters.push(function (v) { return v ? kbService.fxConvert(parseFloat(v), scope.currency) : 0; });\n ngModel.$parsers.push(update);\n };\n return _this;\n }\n KbMoney = __decorate([\n NgComponent({\n token: Token.KbMoney,\n dependencies: [\n Token.KbService,\n Token.$RootScope\n ]\n })\n ], KbMoney);\n return KbMoney;\n }(Directive));\n\n var KbMultiAutoComplete = /** @class */ (function (_super) {\n __extends(KbMultiAutoComplete, _super);\n function KbMultiAutoComplete($q, $timeout) {\n var _this = _super.call(this, $timeout) || this;\n _this.restrict = \"EA\";\n _this.template = Dirs.component(\"kb-multi-auto-complete\");\n _this.scope = _tools.Utils.extend(_this.scope, {\n source: \"&\",\n buildItem: \"&\",\n editable: \"@\",\n valueField: \"@\"\n });\n _this.replace = true;\n _this.transclude = {\n header: \"?kbMultiAutoCompleteHeader\",\n dropdown: \"?kbMultiAutoCompleteDropdown\"\n };\n _this.link = function (scope, element, atts, controllers) {\n _this.kbInputLinkFn(scope, element, atts, controllers);\n var ngModelCtrl = controllers[0];\n if (!atts.ngModel)\n throw new Error(\"ngModel is required for kbAutoSelect\");\n if (!angular.isFunction(scope.source)) {\n throw new Error(\"source for kbMultiAutoComplete must be a function that accepts the current query\");\n }\n if (scope.buildItem && !angular.isFunction(scope.buildItem)) {\n throw new Error(\"buildItem for kbMultiAutoComplete must be a function that accepts the current query\");\n }\n scope._userInput = null;\n scope._matches = [];\n scope._dropdownOpen = false;\n scope._loading = false;\n scope._highlightedItems = {};\n var editable = scope.$parent.$eval(atts.editable) == true;\n var $input = element.find(\"input\");\n scope._isEnabled = function () {\n return !scope.ngDisabled;\n };\n var getMatches = function () {\n var lastUserInput = scope._userInput;\n scope._loading = true;\n var promise = $q.when(scope.source({ query: scope._userInput }));\n promise.then(function (data) {\n // it might happen that several async queries were in progress if a user were typing fast\n // but we are interested only in responses that correspond to the current view value\n if (lastUserInput === scope._userInput) {\n scope._matches.clear();\n scope._matches.pushArray(data);\n scope._activeIndex = -1;\n scope._dropdownOpen = scope._matches.length > 0;\n scope._loading = false;\n }\n });\n };\n scope.$watch(\"_userInput\", function (newUserInput) {\n if (!newUserInput) {\n scope._matches.clear();\n scope._dropdownOpen = false;\n $input.attr(\"size\", 0);\n }\n else {\n $input.attr(\"size\", newUserInput.length);\n getMatches();\n }\n });\n var getValue = function (item) {\n if (item == null)\n return null;\n if (scope.valueField)\n return item[scope.valueField];\n return item;\n };\n var buildItem = function (value) {\n var item = null;\n if (value) {\n if (scope.valueField) {\n item = {};\n item[scope.valueField] = value;\n }\n else {\n item = value;\n }\n // we will add the item right away but come back to it with any modifications from the consumer\n $q.when(scope.buildItem({ value: value })).then(function (builtItem) {\n $.extend(item, builtItem);\n });\n }\n return item;\n };\n scope._selectMatch = function (item) {\n if (scope._isEnabled() && item) {\n var existingItem_1 = scope.ngModel.find(function (i) { return getValue(i) == getValue(item); });\n if (!existingItem_1) {\n // if (typeof item != \"string\") scope.ngModel.push(item);\n // else if (atts[\"valueField\"]) scope.ngModel.push({name: item});\n // else scope.ngModel.push(item);\n scope.ngModel.push(item);\n }\n else {\n scope._highlightedItems[(existingItem_1.name ? existingItem_1.name : existingItem_1)] = true;\n setTimeout(function () {\n scope.$apply(function (scope) {\n scope._highlightedItems[(existingItem_1.name ? existingItem_1.name : existingItem_1)] = false;\n });\n }, 500);\n }\n scope._userInput = \"\";\n }\n };\n scope._itemMousedown = function (e, item) {\n e.preventDefault(); // so we don't lose focus and trigger the blur event\n scope._selectMatch(item);\n };\n scope._delete = function (item) {\n if (scope._isEnabled()) {\n scope.ngModel.remove(item);\n }\n };\n scope._click = function () {\n if (scope._isEnabled()) {\n $input.focus();\n }\n };\n scope._isActive = function (index) {\n return scope._activeIndex == index;\n };\n scope._selectActive = function (index) {\n scope._activeIndex = index;\n };\n $input[0].addEventListener(\"focus\", function () {\n element.addClass(\"focus\");\n });\n $input[0].addEventListener(\"blur\", function () {\n if (editable) {\n scope.$apply(function () {\n scope._selectMatch(buildItem(scope._userInput));\n });\n }\n element.removeClass(\"focus\");\n });\n // bind keyboard events: \n // backspace(8) \n // arrows up(38) /\n // down(40),\n // enter(13) and\n // tab(9),\n // esc(27),\n // space(32)\n // comma(188)\n $input.on(\"keydown\", function (e) {\n if (e.which == _tools.keyboard.backspace) {\n if (!scope._userInput && scope.ngModel.length > 0) {\n scope.$apply(function () {\n scope.ngModel.pop();\n });\n }\n }\n if (e.which == _tools.keyboard.up) {\n e.preventDefault();\n scope.$apply(function () {\n if (scope._dropdownOpen) {\n scope._activeIndex -= 1;\n if (scope._activeIndex < 0) {\n scope._dropdownOpen = false;\n }\n }\n });\n }\n if (e.which == _tools.keyboard.down) {\n e.preventDefault();\n if (scope._activeIndex < scope._matches.length - 1) {\n scope.$apply(function () {\n scope._activeIndex += 1;\n scope._dropdownOpen = true;\n });\n }\n }\n if (e.which == _tools.keyboard.enter) {\n scope.$apply(function () {\n e.preventDefault();\n if (scope._dropdownOpen) {\n if (scope._matches.length > 0) {\n scope._selectMatch(scope._matches[(scope._activeIndex > 0 ? scope._activeIndex : 0)]);\n }\n }\n else if (editable) {\n scope._selectMatch(buildItem(scope._userInput));\n }\n else {\n scope._dropdownOpen = true;\n }\n });\n }\n if (e.which == _tools.keyboard.tab) {\n if (scope._dropdownOpen) {\n if (scope._matches) {\n scope.$apply(function () {\n scope._selectMatch(scope._matches[(scope._activeIndex > 0 ? scope._activeIndex : 0)]);\n });\n }\n e.stopPropagation();\n }\n }\n if (e.which == _tools.keyboard.escape) {\n e.preventDefault();\n scope.$apply(function () {\n scope._dropdownOpen = false;\n e.stopPropagation();\n });\n }\n if ((e.which == _tools.keyboard.comma) && editable) {\n e.preventDefault();\n scope.$apply(function () {\n scope._selectMatch(buildItem(scope._userInput));\n });\n }\n });\n scope.$on(\"$destroy\", function () {\n element.off();\n });\n };\n return _this;\n }\n KbMultiAutoComplete = __decorate([\n NgComponent({\n token: Token.KbMultiAutoComplete,\n dependencies: [\n Token.$Q,\n Token.$Timeout\n ]\n })\n ], KbMultiAutoComplete);\n return KbMultiAutoComplete;\n }(KbInput));\n\n var KbNumberbox = /** @class */ (function (_super) {\n __extends(KbNumberbox, _super);\n function KbNumberbox($timeout) {\n var _this = _super.call(this, $timeout) || this;\n _this.scope = _tools.Utils.extend(_this.scope, {\n format: \"@\",\n minPrecision: \"@\",\n maxPrecision: \"@\",\n currency: \"@\",\n thousandsSeparator: \"@\",\n decimalSeparator: \"@\",\n prefix: \"@\",\n suffix: \"@\",\n step: \"@\"\n });\n _this.template = Dirs.component(\"kb-numberbox\");\n _this.link = function (scope, element, atts, controllers) {\n _this.kbInputLinkFn(scope, element, atts, controllers);\n scope.$watch(\"[ngModel,format,minPrecision,maxPrecision,currency,decimalSeparator,thousandsSeparator,prefix,suffix]\", function () {\n if (scope.ngModel != null && !isNaN(scope.ngModel)) {\n scope._formattedValue = scope.ngModel.format({\n formatType: scope.format,\n minPrecision: Number(scope.minPrecision),\n maxPrecision: Number(scope.maxPrecision),\n currency: scope.currency,\n decimalSeparator: scope.decimalSeparator,\n thousandsSeparator: scope.thousandsSeparator,\n prefix: scope.prefix,\n suffix: scope.suffix\n });\n }\n else {\n scope._formattedValue = \"\";\n }\n });\n };\n return _this;\n }\n KbNumberbox = __decorate([\n NgComponent({\n token: Token.KbNumberbox,\n dependencies: [\n Token.$Timeout\n ]\n })\n ], KbNumberbox);\n return KbNumberbox;\n }(KbInput));\n\n var KbPageTitle = /** @class */ (function (_super) {\n __extends(KbPageTitle, _super);\n function KbPageTitle(kbService) {\n var _this = _super.call(this) || this;\n _this.kbService = kbService;\n _this.restrict = \"EA\";\n _this.template = Dirs.component(\"kb-page-title\");\n _this.transclude = true;\n _this.scope = {\n icon: \"@\",\n label: \"@\",\n desc: \"@\",\n error: \"@\"\n };\n _this.replace = true;\n _this.link = function (scope, element, atts) {\n };\n return _this;\n }\n KbPageTitle = __decorate([\n NgComponent({\n token: Token.KbPageTitle,\n dependencies: [\n Token.KbService\n ]\n })\n ], KbPageTitle);\n return KbPageTitle;\n }(Directive));\n\n // tslint:disable:max-line-length\n var KbPage = /** @class */ (function (_super) {\n __extends(KbPage, _super);\n function KbPage() {\n var _this = _super.call(this) || this;\n _this.replace = true;\n _this.restrict = \"E\";\n _this.scope = true;\n _this.controller = [\n \"$scope\",\n \"$element\",\n \"$attrs\",\n \"$templateCache\",\n Token.$Compile.key,\n Token.$Http.key,\n \"$controller\",\n Token.$Timeout.key,\n \"$animate\",\n \"$transclude\",\n function ($scope, $element, $attrs, $templateCache, $compile, $http, $controller, $timeout, $animate, $transclude) {\n var pageDb = {};\n var oldTemplate;\n var newTemplate;\n var oldTemplateScope;\n var newTemplateScope;\n // because multiple instances of a nested configurator have the same page id, \n // we need to hash it with the configurator name\n var getPageIdentifier = function (page) {\n return page.$parentConfigurator.name + \"-\" + page.id;\n };\n //cache the compiled template since it doesn't change\n var origTemplate = angular.element(Dirs.component(\"kb-page\"));\n var compiled = $compile(origTemplate);\n // pick the right properties page template\n var updateTemplate = function () {\n oldTemplate = newTemplate;\n oldTemplateScope = newTemplateScope;\n // if (oldTemplate) {\n // oldTemplate.removeClass(\"active\");\n // // $timeout(() => {\n // // oldTemplate.remove();\n // // if (oldTemplateScope) {\n // // oldTemplateScope.$destroy();\n // // oldTemplateScope = null;\n // // }\n // // }, 100);\n // }\n // create the new template\n if ($scope.selected && $scope.selected.page) {\n var pageIden_1 = getPageIdentifier($scope.selected.page);\n if (pageDb[pageIden_1]) {\n newTemplate = pageDb[pageIden_1].template;\n newTemplateScope = pageDb[pageIden_1].scope;\n }\n else {\n // newTemplate = angular.element(Dirs.component(\"kb-page\"));\n // let compiled = $compile(newTemplate);\n newTemplateScope = $scope.$new();\n compiled(newTemplateScope, function (clonedElement, scope) {\n clonedElement.addClass(\"kb-page-control__page--initializing\");\n $element.append(clonedElement);\n pageDb[pageIden_1] = {\n scope: newTemplateScope,\n template: clonedElement\n };\n newTemplate = clonedElement;\n });\n // add it to element\n // $element.append(newTemplate);\n }\n newTemplateScope._page = $scope.selected.page;\n //$timeout(() => newTemplate.addClass(\"active\"), 0);\n //$timeout(() => {\n var oldPage_1 = oldTemplateScope ? oldTemplateScope._page : null;\n var newPage_1 = newTemplateScope._page;\n var oldPageIndex_1 = _this.getHierarchicalIndex(oldPage_1);\n var newPageIndex_1 = _this.getHierarchicalIndex(newPage_1);\n var $oldPageEl_1 = oldTemplate;\n var $newPageEl_1 = newTemplate;\n $newPageEl_1.removeClass(\"kb-page-control__page--initializing\");\n newPage_1 && $newPageEl_1.css(\"transition\", \"none\");\n if (_this.isIndexGreater(newPageIndex_1, oldPageIndex_1)) {\n //oldPage && $oldPageEl.css(\"transform\", \"translate3d(-100%,0,0)\");\n newPage_1 && $newPageEl_1.css(\"transform\", \"translate3d(100%,0,0)\");\n }\n else {\n newPage_1 && $newPageEl_1.css(\"transform\", \"translate3d(-100%,0,0)\");\n }\n //if (newPage) newPage.selected = true;\n if (newTemplate)\n newTemplate.addClass(\"kb-page-control__page--selected\");\n setTimeout(function () {\n //animate the height also. \n // let currentHeight = oldPage && $oldPageEl.outerHeight();\n // newPage && $newPageEl.css(\"position\", \"relative\");\n // let newHeight = newPage && $newPageEl.outerHeight(); \n // newPage && $newPageEl.css(\"position\", \"absolute\");\n // $container.height(currentHeight);\n if (_this.isIndexGreater(newPageIndex_1, oldPageIndex_1)) {\n oldPage_1 && $oldPageEl_1.css(\"transform\", \"translate3d(-100%,0,0)\");\n }\n else {\n oldPage_1 && $oldPageEl_1.css(\"transform\", \"translate3d(100%,0,0)\");\n }\n newPage_1 && $newPageEl_1.css(\"transition\", \"\");\n newPage_1 && $newPageEl_1.css(\"transform\", \"translate3d(0,0,0)\");\n // $container.height(newHeight);\n // $timeout(() => {\n // if (oldPage) oldPage.selected = false;\n // //on the first run the new tab element might not have existed until now, so we refresh the reference\n // $newPageEl = newTab && $element.find(`#tab-${newTab.$id}`);\n // newPage && $newPageEl.css(\"position\", \"relative\");\n // oldPage && $oldPageEl.css(\"position\", \"absolute\");\n // $container.height(\"auto\");\n // locked = false;\n // }, 300);\n setTimeout(function () {\n if (oldTemplate)\n oldTemplate.removeClass(\"kb-page-control__page--selected\");\n }, 300);\n }, 0);\n //});\n }\n };\n $scope.selected.pageChanged.add(function (args) {\n updateTemplate();\n });\n $scope.$on(\"$destroy\", function () {\n Object.keys(pageDb).forEach(function (key) {\n if (pageDb[key].scope)\n pageDb[key].scope.$destroy();\n });\n pageDb = null;\n });\n updateTemplate();\n }\n ];\n return _this;\n }\n KbPage.prototype.getHierarchicalIndex = function (parent) {\n var indexMap = [];\n while (parent && parent.$parent) {\n var index = 0;\n if (parent instanceof enums.Page) {\n index = parent.$parent.pages.indexOf(parent);\n }\n else if (parent instanceof enums.Configurator) {\n index = parent.$parent.configurators.indexOf(parent);\n }\n else {\n throw \"unexpected parent type\";\n }\n indexMap.unshift(index);\n parent = parent.$parent;\n }\n return indexMap;\n };\n KbPage.prototype.isIndexGreater = function (thisIndex, otherIndex) {\n for (var i = 0; i < thisIndex.length; i++) {\n if (otherIndex.length == i)\n return true;\n if (thisIndex[i] < otherIndex[i])\n return false;\n if (thisIndex[i] > otherIndex[i])\n return true;\n }\n return false;\n };\n KbPage = __decorate([\n NgComponent({\n token: Token.KbPage,\n dependencies: []\n })\n ], KbPage);\n return KbPage;\n }(Directive));\n\n var KbPassword = /** @class */ (function (_super) {\n __extends(KbPassword, _super);\n function KbPassword($timeout) {\n var _this = _super.call(this, $timeout) || this;\n _this.restrict = \"E\";\n _this.replace = true;\n _this.template = Dirs.component(\"kb-password\");\n return _this;\n }\n KbPassword = __decorate([\n NgComponent({\n token: Token.KbPassword,\n dependencies: [\n Token.$Timeout\n ]\n })\n ], KbPassword);\n return KbPassword;\n }(KbInput));\n\n var KbPrivacyPolicy = /** @class */ (function (_super) {\n __extends(KbPrivacyPolicy, _super);\n function KbPrivacyPolicy($http) {\n var _this = _super.call(this) || this;\n _this.restrict = \"E\";\n _this.replace = true;\n _this.scope = {\n _html: \"=\"\n };\n _this.template = Dirs.component(\"kb-privacy-policy\");\n _this.link = function (scope, element, atts) {\n /*$http.get(\"/privacy.html\").then((d) => {\n scope._html = d.data;\n });*/\n };\n return _this;\n }\n KbPrivacyPolicy = __decorate([\n NgComponent({\n token: Token.KbPrivacyPolicy,\n dependencies: [\n Token.$Http\n ]\n })\n ], KbPrivacyPolicy);\n return KbPrivacyPolicy;\n }(Directive));\n\n var KbProgress = /** @class */ (function (_super) {\n __extends(KbProgress, _super);\n function KbProgress() {\n var _this = _super.call(this) || this;\n _this.restrict = \"EA\";\n _this.replace = true;\n _this.scope = {\n animate: \"=\",\n type: \"@\",\n value: \"@\"\n };\n _this.template = Dirs.component(\"kb-progress\");\n _this.link = function (scope, element, atts) {\n };\n return _this;\n }\n KbProgress = __decorate([\n NgComponent({\n token: Token.KbProgress,\n dependencies: []\n })\n ], KbProgress);\n return KbProgress;\n }(Directive));\n\n var KbRadio = /** @class */ (function (_super) {\n __extends(KbRadio, _super);\n function KbRadio($timeout) {\n var _this = _super.call(this, $timeout) || this;\n _this.scope = _tools.Utils.extend(_this.scope, {\n source: \"=\",\n valueField: \"@\",\n labelField: \"@\",\n data: \"=?\"\n });\n _this.transclude = true;\n _this.template = Dirs.component(\"kb-radio\");\n _this.link = function (scope, element, atts, controllers) {\n _this.kbInputLinkFn(scope, element, atts, controllers, false);\n var ngModel = controllers[0];\n scope._id = _tools.Utils.shortId();\n scope._getItemValue = function (item) {\n if (item === null || item === undefined)\n return null;\n return scope.valueField ? item[scope.valueField] : item;\n };\n scope._select = function (item) {\n if (!scope.ngDisabled) {\n ngModel.$setViewValue(scope._getItemValue(item));\n }\n };\n scope._itemKeydown = function (e, item) {\n if (e.key == 'Enter' || e.key == ' ' && !scope.ngDisabled) {\n scope._select(item);\n e.preventDefault();\n }\n else if (e.key == 'Escape') {\n // element.find(\"input\").blur();\n element.find(\".kb-radio__item\").trigger('blur');\n }\n };\n };\n return _this;\n }\n KbRadio = __decorate([\n NgComponent({\n token: Token.KbRadio,\n dependencies: [\n Token.$Timeout,\n ]\n })\n ], KbRadio);\n return KbRadio;\n }(KbInput));\n\n var KbResize = /** @class */ (function (_super) {\n __extends(KbResize, _super);\n function KbResize() {\n var _this = _super.call(this) || this;\n _this.restrict = \"E\";\n _this.replace = true;\n _this.transclude = true;\n _this.scope = {\n handles: \"@\",\n containment: \"@\",\n minWidth: \"@\",\n maxWidth: \"@\",\n minHeight: \"@\",\n maxHeight: \"@\",\n onStop: \"&\",\n resizeDisabled: \"=?\"\n };\n _this.template = Dirs.component(\"kb-resize\");\n _this.link = function (scope, elem, atts) {\n if (scope.minWidth)\n elem.css(\"min-width\", scope.minWidth);\n if (scope.maxWidth)\n elem.css(\"max-width\", scope.maxWidth);\n if (scope.minHeight)\n elem.css(\"min-height\", scope.minHeight);\n if (scope.maxHeight)\n elem.css(\"max-height\", scope.maxHeight);\n var exists = false;\n var createResizable = function () {\n elem.resizable({\n handles: scope.handles,\n containment: scope.containment || \"parent\",\n stop: function () {\n if (scope.onStop)\n scope.onStop();\n }\n });\n exists = true;\n };\n var destroyResizable = function () {\n if (exists)\n elem.resizable(\"destroy\");\n exists = false;\n };\n // resizable doesn't handle flexbox well so we override the resize method for our own custom logic\n var resize = function (event, ui) {\n ui.position.left = ui.originalPosition.left;\n };\n elem.on(\"resize\", resize);\n scope.$watch(\"handles\", function () {\n if (exists)\n elem.resizable(\"option\", \"handles\", scope.handles);\n });\n scope.$watch(\"disabled\", function () {\n if (scope.resizeDisabled) {\n destroyResizable();\n }\n else {\n createResizable();\n }\n });\n scope.$on(\"$destroy\", function () {\n elem.off(\"resize\");\n destroyResizable();\n });\n };\n return _this;\n }\n KbResize = __decorate([\n NgComponent({\n token: Token.KbResize,\n dependencies: []\n })\n ], KbResize);\n return KbResize;\n }(Directive));\n\n var KbRipple = /** @class */ (function (_super) {\n __extends(KbRipple, _super);\n function KbRipple($rootScope) {\n var _this = _super.call(this) || this;\n _this.restrict = \"A\";\n _this.scope = false;\n _this.link = function (scope, element, atts) {\n var checkbox = scope.$eval(atts.kbRippleCheckbox);\n var $ripple;\n var $wave;\n var ripples = [];\n var last;\n var duration = 300;\n if (!checkbox) {\n element.addClass(\"kb-ripple--hover\");\n }\n var rippleShow = function (e) {\n var rippleDisabled = scope.$eval(atts.kbRippleDisabled) === true;\n if (!rippleDisabled) {\n if (element.closest(\"[disabled]\").length) {\n return;\n }\n var initPos = element.css(\"position\");\n var offset = element.offset();\n var elWidth = element[0].offsetWidth;\n var elHeight = element[0].offsetHeight;\n var dia = Math.max(elHeight, elWidth) * 2; // start diameter\n var x_1 = checkbox ? \"50%\" : e.pageX - offset.left - (dia / 2) + \"px\";\n var y_1 = checkbox ? \"50%\" : e.pageY - offset.top - (dia / 2) + \"px\";\n var scale_1 = checkbox ? 2.88 : 1;\n $ripple = $('
', {\n class: \"kb-ripple\",\n appendTo: element,\n css: {\n overflow: checkbox ? \"visible\" : \"hidden\"\n }\n });\n ripples.push($ripple);\n if (!initPos || initPos === \"static\") {\n element.css({ position: \"relative\" });\n }\n $wave = $('
', {\n class: \"kb-ripple__wave kb-ripple__wave--enter kb-ripple__wave--visible\" + (checkbox ? \" kb-ripple__wave--checkbox\" : \"\"),\n css: {\n width: checkbox ? \"1.2rem\" : dia,\n height: checkbox ? \"1.2rem\" : dia,\n transform: \"translate(\".concat(x_1, \", \").concat(y_1, \") scale3d(0,0,0)\"),\n marginLeft: checkbox ? \"-.6rem\" : 0,\n marginTop: checkbox ? \"-.6rem\" : 0\n },\n appendTo: $ripple,\n // one: {\n // animationend: function () {\n // $ripple.remove();\n // }\n // }\n });\n setTimeout(function () {\n $wave.removeClass(\"kb-ripple__wave--enter\");\n $wave.css(\"transform\", \"translate(\".concat(x_1, \", \").concat(y_1, \") scale3d(\").concat(scale_1, \", \").concat(scale_1, \", \").concat(scale_1, \")\"));\n last = performance.now();\n }, 0);\n }\n };\n var rippleHide = function () {\n if (!element || !$ripple || !$wave)\n return;\n var delay = Math.max(duration - (performance.now() - last), 0);\n setTimeout(function () {\n $wave.removeClass(\"kb-ripple__wave--visible\");\n setTimeout(function () {\n ripples.forEach(function (r) { return r.remove(); });\n }, duration);\n }, delay);\n };\n element.on(\"pointerdown\", rippleShow);\n element.on('pointerup', rippleHide);\n element.on('pointerleave', rippleHide);\n element.on('dragstart', rippleHide);\n scope.$on(\"$destroy\", function () {\n element.off();\n });\n };\n return _this;\n }\n KbRipple = __decorate([\n NgComponent({\n token: Token.KbRipple,\n dependencies: [\n Token.$RootScope\n ]\n })\n ], KbRipple);\n return KbRipple;\n }(Directive));\n\n /**\n * KbScope\n *\n * Allows you to create a new prototypically inherited scope on an element. Consider this example:\n *
\n * \n *
\n *\n * kbScope will put everything inside of the div into a new scope with the item property set on it\n * It accomplishes this by using transclusion\n */\n var KbScope = /** @class */ (function (_super) {\n __extends(KbScope, _super);\n function KbScope() {\n var _this = _super.call(this) || this;\n _this.restrict = \"A\";\n _this.scope = false;\n _this.priority = 1000; // make sure it runs first\n _this.transclude = \"element\";\n _this.link = function (scope, element, atts, ctrl, $transclude) {\n var childScope = scope.$new();\n scope.$watch(\"{\" + atts.kbScope + \"}\", function (data) {\n angular.extend(childScope, data);\n }, true);\n $transclude(childScope, function (clone) {\n element.after(clone);\n });\n scope.$on(\"$destroy\", function () {\n if (childScope)\n childScope.$destroy();\n });\n };\n return _this;\n }\n KbScope = __decorate([\n NgComponent({\n token: Token.KbScope,\n dependencies: []\n })\n ], KbScope);\n return KbScope;\n }(Directive));\n\n var KbSearchGrid = /** @class */ (function (_super) {\n __extends(KbSearchGrid, _super);\n function KbSearchGrid(drawerService) {\n var _this = _super.call(this) || this;\n _this.template = Dirs.component(\"kb-search-grid\");\n _this.restrict = \"AE\";\n _this.scope = false;\n _this.replace = true;\n _this.transclude = {\n results: '?kbSearchGridResults',\n customResults: '?kbSearchGridCustomResults',\n toolbar: '?kbSearchGridToolbar'\n };\n _this.controller = [\n \"$scope\",\n \"$element\",\n \"$attrs\",\n \"$transclude\",\n Token.ApiService.key,\n function ($scope, $element, $attrs, $transclude, api) {\n var columns = $scope.columns = [];\n $scope.scrollParent = $attrs.scrollParent || \"#search-content\";\n $scope.drawerService = drawerService;\n var colDb = {};\n this.addColumn = function (column) {\n if (!colDb[column.id]) {\n colDb[column.id] = column;\n columns.push(column);\n columns.sortBy(function (c) { return c.order; });\n // column.$on(\"$destroy\", (event) => {\n // columns.remove(column);\n // });\n // set sort properties from query string \n if (column.field && column.field == $scope.binding.search.sortField) {\n column.sorted = true;\n column.descending = $scope.binding.search.descending;\n }\n }\n };\n }\n ];\n return _this;\n }\n KbSearchGrid = __decorate([\n NgComponent({\n token: Token.KbSearchGrid,\n dependencies: [\n Token.DrawerService\n ]\n })\n ], KbSearchGrid);\n return KbSearchGrid;\n }(Directive));\n\n var KbSelect = /** @class */ (function (_super) {\n __extends(KbSelect, _super);\n function KbSelect($timeout, $window) {\n var _this = _super.call(this, $timeout) || this;\n _this.template = Dirs.component(\"kb-select\");\n _this.scope = _tools.Utils.extend(_this.scope, {\n source: \"=\",\n data: \"=?\",\n valueField: \"@\",\n labelField: \"@\",\n defaultLabel: \"@\",\n headerTemplate: \"@\",\n mobileDropdown: \"=?\",\n filter: \"=\",\n itemStyle: \"=?\",\n deepWatch: \"=?\",\n optionLayout: \"=?\"\n });\n _this.transclude = true;\n _this.compile = function (element, atts) {\n if (atts.mobileDropdown == null)\n atts.mobileDropdown = \"true\";\n return _this.link;\n };\n _this.controller = [\n \"$scope\",\n \"$element\",\n \"$attrs\",\n \"$transclude\",\n \"$templateCache\",\n Token.$Compile.key,\n function ($scope, $element, $attrs, $transclude, $templateCache, $compile) {\n // set the scope on the controller so children can access it\n this.scope = $scope;\n // if a header template was passed in then get it from the template cache\n if ($scope.headerTemplate) {\n var $template = angular.element($templateCache.get($scope.headerTemplate));\n // compile the template\n var compiled = $compile($template, $transclude);\n // append it to the label\n $element.find(\".kb-select__header\").html(\"\").append($template);\n // now link it to the parent scope(we don't want this scope because it's an isolate scope)\n compiled($scope);\n }\n }\n ];\n _this.link = function (scope, element, atts, controllers) {\n // we provide out own implementation of isEmpty to kbInput since a value because null is an allowed value that could have a label\n // this is for material design so we know when to float the label\n var isEmpty = function (val) {\n return scope._selectedLabel == null || scope._selectedLabel.length == 0;\n };\n _this.kbInputLinkFn(scope, element, atts, controllers, true, isEmpty);\n var ngModelCtrl = controllers[0];\n scope._id = _tools.Utils.shortId();\n scope._binding = { query: \"\" };\n var input = element.find(\"input\");\n // the source as an array (it might have been passed in as a function so we normalize it)\n var arraySource;\n //readyForValue tracks wether a value has been chosen for the select list or not \n var readyForValue = false;\n var getItemValue = function (item) {\n if (item === null || item === undefined)\n return null;\n return scope.valueField ? item[scope.valueField] : item;\n };\n var getItemLabel = function (item) {\n var _a, _b;\n if (scope.labelField && item[scope.labelField] && ((_a = item[scope.labelField]) === null || _a === void 0 ? void 0 : _a.toString())) {\n return (_b = item[scope.labelField]) === null || _b === void 0 ? void 0 : _b.toString();\n }\n else if (scope.valueField) {\n return item[scope.valueField];\n }\n else {\n return item;\n }\n };\n var updateSelectedLabel = function () {\n scope._selectedLabel = scope.item ? getItemLabel(scope.item) : scope.defaultLabel;\n };\n var isEnabled = function () {\n return !scope.ngDisabled;\n };\n var updateSelected = function () {\n if (arraySource) {\n for (var i = 0; i < arraySource.length; i++) {\n var item = arraySource[i];\n if (getItemValue(item) == ngModelCtrl.$viewValue) {\n scope.item = item;\n scope._selectedIndex = i;\n scope._activeIndex = i;\n updateSelectedLabel();\n scope._setHasValue(!isEmpty());\n return;\n }\n }\n }\n // if we get here, then it wasn't found.\n scope.item = null;\n updateSelectedLabel();\n scope._setHasValue(!isEmpty());\n };\n var showDropdown = function () {\n scope._dropdownOpen = true;\n readyForValue = true;\n // on mobile the filter input will kick off the keyboard, which we don't necessarily want. \n // The problem is worse on IOS because of focus restrictions\n if ($window.innerWidth >= _tools.Utils.MOBILE_WIDTH && !_tools.Utils.isIos()) {\n $timeout(function () { return input.trigger('focus'); });\n if (scope.source.length > 10) {\n var searchBox_1 = document.getElementById(scope._id + \"-input\");\n $timeout(function () { return searchBox_1.focus(); });\n }\n }\n };\n var hideDropdown = function () {\n scope._dropdownOpen = false;\n scope._binding.query = null;\n updateFilteredSource();\n };\n var toggleDropdown = function () {\n scope._dropdownOpen ? hideDropdown() : showDropdown();\n };\n // options might be added after the ngModel is set by the consumer, so\n // we need to refind the selected option \n var sourceChange = function () {\n if (angular.isFunction(scope.source)) {\n arraySource = scope.source();\n }\n else {\n arraySource = scope.source;\n }\n updateSelected();\n updateFilteredSource();\n };\n if (scope.deepWatch) {\n scope.$watch(\"source\", function () { return sourceChange(); }, true);\n }\n else {\n scope.$watchCollection(\"source\", function () { return sourceChange(); });\n }\n ngModelCtrl.$render = function () {\n updateSelected();\n };\n scope._itemMousedown = function (e, item) {\n e.preventDefault(); // so we don't lose focus\n scope._select(item);\n };\n scope._select = function (item) {\n if (readyForValue) {\n if (isEnabled()) {\n readyForValue = false;\n hideDropdown();\n ngModelCtrl.$setViewValue(getItemValue(item));\n updateSelected();\n }\n }\n };\n scope._click = function (e) {\n if (isEnabled()) {\n toggleDropdown();\n }\n };\n scope._isActive = function (index) {\n return index === scope._activeIndex;\n };\n var updateFilteredSource = function () {\n if (!scope._binding.query) {\n scope._filteredSource = arraySource;\n }\n else {\n scope._filteredSource = _tools.SearchUtils.search(scope._binding.query, arraySource, function (o) { var _a; return (_a = getItemLabel(o)) === null || _a === void 0 ? void 0 : _a.toString(); }, 10000);\n scope._activeIndex = 0;\n }\n };\n scope._queryChange = function (e) {\n updateFilteredSource();\n };\n scope._queryKeydown = function (e) {\n if (e.key == \"ArrowUp\") {\n moveUp();\n e.stopPropagation();\n }\n if (e.key == \"ArrowDown\") {\n moveDown();\n e.stopPropagation();\n }\n if (e.key === \"Enter\") {\n enter();\n e.stopPropagation();\n }\n if (e.key === \"Tab\") {\n tab();\n if (scope._dropdownOpen) {\n e.stopPropagation();\n e.preventDefault();\n }\n }\n };\n var moveUp = function () {\n if (scope._dropdownOpen) {\n // if we are already at index zero, then close the dropdown\n var newIndex = scope._activeIndex - 1;\n if (newIndex >= 0)\n scope._activeIndex = newIndex;\n }\n };\n var moveDown = function () {\n showDropdown();\n // if we are already at index zero, then close the dropdown\n var newIndex = scope._activeIndex + 1;\n if (newIndex < scope._filteredSource.length)\n scope._activeIndex = newIndex;\n };\n var enter = function () {\n if (scope._dropdownOpen) {\n if (scope._filteredSource.length && scope._activeIndex > -1) {\n scope._select(scope._filteredSource[scope._activeIndex]);\n }\n element.trigger(\"focus\");\n }\n else {\n showDropdown();\n }\n };\n var tab = function () {\n if (scope._dropdownOpen) {\n element.trigger('focus');\n if (scope._filteredSource.length && scope._activeIndex > -1) {\n scope._select(scope._filteredSource[scope._activeIndex]);\n }\n }\n };\n var keySearch = function (key) {\n var _a, _b, _c, _d;\n key = key.toLowerCase();\n var option = scope._activeIndex;\n var labelOrValue = (_b = (_a = scope._filteredSource[option].label) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : scope._filteredSource[option].value;\n if (labelOrValue && !labelOrValue.toLowerCase().startsWith(key)) {\n option = scope._filteredSource.findIndex(function (a) {\n var _a;\n var b = ((_a = a.label) === null || _a === void 0 ? void 0 : _a.toString()) || a.value;\n return b.toLowerCase().startsWith(key);\n });\n }\n else {\n if ((option + 1) < scope._filteredSource.length) {\n var optionPlusOne = (_d = (_c = scope._filteredSource[(option + 1)].label) === null || _c === void 0 ? void 0 : _c.toString()) !== null && _d !== void 0 ? _d : scope._filteredSource[(option + 1)].value;\n if (optionPlusOne && optionPlusOne.toLowerCase().startsWith(key)) {\n option++;\n }\n else {\n option = scope._filteredSource.findIndex(function (a) {\n var _a, _b;\n var b = (_b = (_a = a.label) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : a.value;\n return b.toLowerCase().startsWith(key);\n });\n }\n }\n else {\n option = scope._filteredSource.findIndex(function (a) {\n var _a, _b;\n var b = (_b = (_a = a.label) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : a.value;\n return b === null || b === void 0 ? void 0 : b.toLowerCase().startsWith(key);\n });\n }\n }\n if (option > -1) {\n showDropdown();\n scope._activeIndex = option;\n }\n };\n // bind keyboard events: arrows up(38) / down(40), enter(13) and tab(9), esc(27)\n element.on(\"keydown\", function (e) {\n switch (e.key) {\n case 'ArrowUp':\n e.preventDefault();\n scope.$apply(function () {\n moveUp();\n });\n break;\n case 'ArrowDown':\n e.preventDefault();\n scope.$apply(function () {\n moveDown();\n });\n break;\n case 'Enter':\n scope.$apply(function () {\n e.preventDefault();\n enter();\n });\n break;\n case 'Tab':\n scope.$apply(function () {\n if (scope._dropdownOpen) {\n e.stopPropagation();\n e.preventDefault();\n }\n tab();\n });\n break;\n case 'Escape':\n e.preventDefault();\n scope.$apply(function () {\n hideDropdown();\n e.stopPropagation();\n });\n element.trigger('blur');\n break;\n default:\n if (e.key.match(/^[a-zA-Z,0-9]+$/) && e.key.length == 1) {\n e.stopPropagation();\n e.preventDefault();\n scope.$apply(function () {\n keySearch(e.key);\n });\n }\n break;\n }\n });\n scope.$on(\"$destroy\", function () {\n element.off();\n });\n };\n return _this;\n }\n KbSelect = __decorate([\n NgComponent({\n token: Token.KbSelect,\n dependencies: [\n Token.$Timeout,\n Token.$Window,\n ]\n })\n ], KbSelect);\n return KbSelect;\n }(KbInput));\n\n var KbSfdcHeader = /** @class */ (function (_super) {\n __extends(KbSfdcHeader, _super);\n function KbSfdcHeader($timeout, drawerService) {\n var _this = _super.call(this) || this;\n _this.restrict = \"EA\";\n _this.template = Dirs.component(\"kb-sfdc-header\");\n _this.scope = false;\n _this.replace = true;\n _this.controller = [\n \"$scope\",\n \"$element\",\n \"$attrs\",\n \"$transclude\",\n \"$templateCache\",\n Token.$Compile.key,\n function ($scope, $element, $attrs, $transclude, $templateCache, $compile) {\n // set the scope on the controller so children can access it\n this.scope = $scope;\n $scope.drawerService = drawerService;\n }\n ];\n _this.link = function (scope, element, atts, ngModel) {\n };\n return _this;\n }\n KbSfdcHeader = __decorate([\n NgComponent({\n token: Token.KbSfdcHeader,\n dependencies: [\n Token.$Timeout,\n Token.DrawerService,\n ]\n })\n ], KbSfdcHeader);\n return KbSfdcHeader;\n }(Directive));\n\n var KbSlide = /** @class */ (function (_super) {\n __extends(KbSlide, _super);\n function KbSlide() {\n var _this = _super.call(this) || this;\n _this.restrict = \"EA\";\n _this.replace = true;\n _this.scope = {\n open: \"=\"\n };\n _this.transclude = true;\n _this.template = Dirs.component(\"kb-slide\");\n _this.link = function (scope, element, atts) {\n // put a class on the body element in the form of\n // -visible so that other elements can react\n // to the slide being open\n if (atts.id) {\n var className_1 = atts.id + \"-open\";\n scope.$watch(\"open\", function (newValue) {\n if (angular.isDefined(newValue)) {\n $(\"body\").toggleClass(className_1, newValue);\n }\n });\n }\n scope.clicked = function () {\n scope.open = false;\n };\n scope.$watch(\"open\", function (newValue) {\n if (!newValue) {\n $(element).find(\".kb-slide__nav\").scrollTop(0);\n }\n });\n };\n return _this;\n }\n KbSlide = __decorate([\n NgComponent({\n token: Token.KbSlide,\n dependencies: []\n })\n ], KbSlide);\n return KbSlide;\n }(Directive));\n\n var KbSlider = /** @class */ (function (_super) {\n __extends(KbSlider, _super);\n function KbSlider($timeout, $document) {\n var _this = _super.call(this, $timeout) || this;\n _this.scope = _tools.Utils.extend(_this.scope, {\n min: \"=\",\n max: \"=\",\n step: \"=?\",\n format: \"@\",\n minPrecision: \"@\",\n maxPrecision: \"@\",\n currency: \"@\",\n thousandsSeparator: \"@\",\n decimalSeparator: \"@\",\n prefix: \"@\",\n suffix: \"@\",\n directEdit: \"=?\",\n valueVisibility: \"=?\"\n });\n _this.template = Dirs.component(\"kb-slider\");\n _this.link = function (scope, element, atts, controllers) {\n _this.kbInputLinkFn(scope, element, atts, controllers);\n var ngModel = controllers[0];\n var $thumb = element.find(\".kb-slider__thumb\");\n var thumbElem = $thumb[0];\n var lineElem = element.find(\".kb-slider__line\")[0];\n var valueLineElem = element.find(\".kb-slider__value-line\")[0];\n var setViewValue = function (val) {\n ngModel.$setViewValue(val);\n setFormattedValue(val);\n };\n var getNearestVal = function (tryVal) {\n var steps = Math.floor(scope.max / scope.step);\n var val = Math.round(tryVal / scope.step) * scope.step;\n val = Math.min(scope.max, Math.max(val, scope.min));\n return val;\n };\n var setCurrentValue = function (val) {\n scope.currentVal = val;\n return val;\n };\n var setThumbPos = function (val, withAnimation) {\n if (withAnimation === void 0) { withAnimation = true; }\n var clientWidth = lineElem.clientWidth;\n var percent = (val - scope.min) / (scope.max - scope.min);\n percent = Math.max(Math.min(1, percent), 0);\n var cssVal = \"\".concat(percent * 100, \"%\");\n if (withAnimation) {\n $(thumbElem).stop(true, true).animate({ left: cssVal }, 300, \"easeInOutCubic\");\n $(valueLineElem).stop(true, true).animate({ width: cssVal }, 300, \"easeInOutCubic\");\n }\n else {\n thumbElem.style.left = cssVal;\n valueLineElem.style.width = cssVal;\n }\n return val;\n };\n var getValFromMousePos = function (mouseClientX) {\n var lineRect = lineElem.getBoundingClientRect();\n var lineWidth = lineRect.right - lineRect.left;\n var percent = (mouseClientX - lineRect.left) / lineWidth;\n var cval = ((scope.max - scope.min) * percent) + scope.min;\n cval = cval.rounder(scope.maxPrecision);\n cval = getNearestVal(cval);\n return cval;\n };\n var setFormattedValue = function (value) {\n var format = scope.format;\n if (!format || format == enums.eFormatType.none)\n format = enums.eFormatType.number;\n scope.formattedValue = value.format({\n formatType: format,\n minPrecision: Number(scope.minPrecision),\n maxPrecision: Number(scope.maxPrecision),\n currency: scope.currency,\n decimalSeparator: scope.decimalSeparator,\n thousandsSeparator: scope.thousandsSeparator,\n prefix: scope.prefix,\n suffix: scope.suffix\n });\n return value;\n };\n var setTicks = function (val) {\n scope.tickPercent = Math.min(Math.max(scope.step / (scope.max - scope.min), .01), 1);\n return val;\n };\n //formatters are run in reverse\n ngModel.$formatters.push(setTicks);\n ngModel.$formatters.push(setFormattedValue);\n ngModel.$formatters.push(setThumbPos);\n ngModel.$formatters.push(setCurrentValue);\n ngModel.$formatters.push(getNearestVal);\n scope.lineClick = function (e) {\n if (!scope.ngDisabled) {\n var cval = getValFromMousePos(e.clientX);\n setCurrentValue(cval);\n setThumbPos(cval, true);\n setViewValue(cval);\n // scope.ngModel = cval; // set ngmodel instead of setViewValue so that it runs through all the formatters again\n }\n };\n var pointerdown = function (e) {\n if (!scope.ngDisabled) {\n scope.dragging = true;\n $document.attr(\"touch-action\", \"none\");\n $document.on(\"pointerup\", pointerup);\n $document.on(\"pointermove\", pointermove);\n scope.$digest();\n }\n };\n var pointerup = function (e) {\n if (!scope.ngDisabled) {\n scope.dragging = false;\n $document.attr(\"touch-action\", \"\");\n $document.off(\"pointerup\", pointerup);\n $document.off(\"pointermove\", pointermove);\n setViewValue(scope.currentVal);\n scope.$digest();\n }\n };\n var pointermove = function (e) {\n if (!scope.ngDisabled) {\n var cval = getValFromMousePos(e.clientX);\n scope.currentVal = cval;\n setThumbPos(cval, false);\n setFormattedValue(cval);\n scope.$digest();\n }\n };\n var keydown = function (e) {\n if (!scope.ngDisabled) {\n if (e.key == 'ArrowLeft') { //arrow left\n var cval = getNearestVal(scope.ngModel - scope.step);\n scope.currentVal = cval;\n setThumbPos(cval, false);\n setViewValue(cval);\n scope.$digest();\n }\n else if (e.key == 'ArrowRight') { //arrow right\n var cval = getNearestVal(scope.ngModel + scope.step);\n scope.currentVal = cval;\n setThumbPos(cval, false);\n setViewValue(cval);\n scope.$digest();\n }\n else if (e.key == 'Escape') {\n element.trigger('blur');\n }\n }\n };\n // we need to add the touch-action attribute to the svg element for the pep library\n // for the pointer-events w3c standard, this will be replaced by a css attribute\n $thumb.attr(\"touch-action\", \"none\");\n $thumb.on(\"pointerdown\", pointerdown);\n element.on(\"keydown\", keydown);\n scope.$watch(\"min\", function (newVal) {\n setThumbPos(scope.ngModel);\n setTicks(scope.ngModel);\n });\n scope.$watch(\"max\", function (newVal) {\n setThumbPos(scope.ngModel);\n setTicks(scope.ngModel);\n });\n scope.$watch(\"step\", function (newVal) {\n setThumbPos(scope.ngModel);\n setTicks(scope.ngModel);\n });\n scope.$on(\"$destroy\", function () {\n element.off();\n $document.off(\"pointerup\", pointerup);\n $document.off(\"pointermove\", pointermove);\n });\n };\n return _this;\n }\n KbSlider = __decorate([\n NgComponent({\n token: Token.KbSlider,\n dependencies: [\n Token.$Timeout,\n Token.$Document\n ]\n })\n ], KbSlider);\n return KbSlider;\n }(KbInput));\n\n var KbSpinnerElement = /** @class */ (function (_super) {\n __extends(KbSpinnerElement, _super);\n function KbSpinnerElement() {\n var _this = _super.call(this) || this;\n _this.restrict = \"E\";\n _this.scope = {\n tracker: \"=?\",\n show: \"=?\",\n label: \"=?\"\n };\n _this.replace = true;\n _this.template = \"
\" +\n \"
\" +\n \"
\" +\n \"
\" +\n \"
\" +\n \"
\" +\n \"
\" +\n \"
\" +\n \"
\" +\n \"
\" +\n \"
{{label}}
\" +\n \"
\";\n _this.link = function (scope, element, atts) {\n // get the template\n };\n return _this;\n }\n KbSpinnerElement = __decorate([\n NgComponent({\n token: Token.KbSpinnerElement,\n dependencies: []\n })\n ], KbSpinnerElement);\n return KbSpinnerElement;\n }(Directive));\n\n var KbSpinner = /** @class */ (function (_super) {\n __extends(KbSpinner, _super);\n function KbSpinner($http, $compile, $rootScope) {\n var _this = _super.call(this) || this;\n _this.$http = $http;\n _this.$compile = $compile;\n _this.$rootScope = $rootScope;\n _this.restrict = \"A\";\n _this.scope = true;\n _this.link = function (scope, element, atts) {\n scope._tracker = scope.$eval(atts.kbSpinner);\n // get the template\n var template = \"
\" +\n \"
\" +\n \"
\" +\n \"
\" +\n \"
\" +\n \"
\" +\n \"
\" +\n \"
\" +\n \"
\" +\n \"
\" +\n \"
\";\n var templateElement = $compile(template)(scope);\n element.append(templateElement);\n };\n return _this;\n }\n KbSpinner = __decorate([\n NgComponent({\n token: Token.KbSpinner,\n dependencies: [\n Token.$Http,\n Token.$Compile,\n Token.$RootScope,\n ]\n })\n ], KbSpinner);\n return KbSpinner;\n }(Directive));\n\n var KbSrcOnError = /** @class */ (function (_super) {\n __extends(KbSrcOnError, _super);\n function KbSrcOnError() {\n var _this = _super.call(this) || this;\n _this.restrict = \"A\";\n _this.link = function (scope, element, atts, ctrl, $transclude) {\n element.on('error', function () {\n element.attr('src', atts.kbSrcOnError);\n });\n };\n return _this;\n }\n KbSrcOnError = __decorate([\n NgComponent({\n token: Token.KbSrcOnError\n })\n ], KbSrcOnError);\n return KbSrcOnError;\n }(Directive));\n\n /**\n * Given markdown text in the ngModel, will display the html\n */\n var KbSvgViewer = /** @class */ (function (_super) {\n __extends(KbSvgViewer, _super);\n function KbSvgViewer($timeout) {\n var _this = _super.call(this) || this;\n _this.scope = {\n ngModel: \"=\",\n width: \"=?\",\n height: \"=?\",\n svgWidth: \"=?\",\n svgHeight: \"=?\",\n svgStyle: \"=?\",\n kbDragStart: \"&\",\n kbDragMove: \"&\",\n kbDragEnd: \"&\",\n kbClick: \"&\",\n defs: \"=?\",\n maxZoom: \"=?\",\n minZoom: \"=?\",\n disablePan: \"=?\",\n disableZoom: \"=?\",\n zoomLevel: \"=?\",\n panX: \"=?\",\n panY: \"=?\"\n };\n _this.restrict = \"E\";\n _this.template = Dirs.component(\"kb-svg-viewer\", exports.eBundle.app);\n _this.replace = true;\n _this.require = \"ngModel\";\n _this.transclude = true;\n _this.link = function (scope, element, atts, ngModel) {\n scope.svg = { width: \"0\", height: \"0\" };\n if (!scope.svgStyle)\n scope.svgStyle = \"\";\n if (!scope.minZoom)\n scope.minZoom = 0.124;\n if (!scope.maxZoom)\n scope.maxZoom = 4;\n if (!scope.zoomLevel)\n scope.zoomLevel = 1;\n if (!scope.panX)\n scope.panX = 0;\n if (!scope.panY)\n scope.panY = 0;\n var tolerance = 10;\n var isDown = false;\n var dragged = false;\n var baseMouse;\n var svg = element.find(\"svg\");\n var g = svg.find(\"g\");\n var svgDims = {\n width: 0,\n height: 0,\n scale: scope.zoomLevel,\n scrollX: scope.panX,\n scrollY: scope.panY\n };\n var svgWidthIsAuto = function () { return !scope.svgWidth || scope.svgWidth == \"auto\"; };\n var svgHeightIsAuto = function () { return !scope.svgHeight || scope.svgHeight == \"auto\"; };\n if (!svgWidthIsAuto()) {\n svgDims.width = parseFloat(scope.svgWidth);\n }\n if (!svgHeightIsAuto()) {\n svgDims.height = parseFloat(scope.svgHeight);\n }\n scope.$watch(\"zoomLevel\", function (level) {\n svgDims.scale = level;\n svgDims.scale = Math.min(Math.max(scope.minZoom, svgDims.scale), scope.maxZoom);\n updateSvg();\n });\n scope.$watch(\"panX\", function (x) {\n svgDims.scrollX = x;\n svgDims.scrollX = Math.min(Math.max(-svg.outerWidth() * svgDims.scale, svgDims.scrollX), svg.outerWidth() * svgDims.scale);\n updateSvg();\n });\n scope.$watch(\"panY\", function (y) {\n svgDims.scrollY = y;\n svgDims.scrollY = Math.min(Math.max(-svg.outerHeight() * svgDims.scale, svgDims.scrollY), svg.outerHeight() * svgDims.scale);\n updateSvg();\n });\n var getEvent = function (e) {\n var svgWidth = svg.outerWidth();\n var svgHeight = svg.outerHeight();\n var modifierX = svgDims.width / svgWidth;\n var modifierY = svgDims.height / svgHeight;\n var event = {\n offsetX: e.offsetX * modifierX + svgDims.scrollX * modifierX,\n offsetY: e.offsetY * modifierY + svgDims.scrollY * modifierY,\n target: e.target,\n currentTarget: e.currentTarget\n };\n return event;\n };\n var updateSvg = function (recalculateSize) {\n if (recalculateSize === void 0) { recalculateSize = true; }\n if (recalculateSize) {\n if (svgWidthIsAuto()) {\n svgDims.width = 0;\n }\n else {\n svgDims.width = (parseInt(scope.svgWidth));\n }\n if (svgHeightIsAuto()) {\n svgDims.height = 0;\n }\n else {\n svgDims.height = (parseInt(scope.svgHeight));\n }\n g.children().each(function () {\n var thisEl = jQuery(this)[0];\n if (thisEl.getBBox) {\n var bbox = thisEl.getBBox();\n var xPos = (bbox.x + bbox.width);\n var yPos = (bbox.y + bbox.height);\n if (svgWidthIsAuto()) {\n if (xPos > svgDims.width)\n svgDims.width = xPos;\n }\n if (svgHeightIsAuto()) {\n if (yPos > svgDims.height)\n svgDims.height = yPos;\n }\n }\n });\n }\n scope.svg.width = svgDims.width * svgDims.scale;\n scope.svg.height = svgDims.height * svgDims.scale;\n var render = function () {\n g.attr(\"transform\", \"scale(\".concat(svgDims.scale, \", \").concat(svgDims.scale, \")\"));\n //element.scrollLeft(svgDims.scrollX);\n //element.scrollTop(svgDims.scrollY);\n var svgWidth = svg.outerWidth();\n var svgHeight = svg.outerHeight();\n var modifierX = svgDims.width / svgWidth;\n var modifierY = svgDims.height / svgHeight;\n var viewBoxX = (svgDims.scrollX * modifierX);\n var viewBoxY = (svgDims.scrollY * modifierY);\n if (!isNaN(viewBoxX) && !isNaN(viewBoxY)) {\n svg.attr(\"viewBox\", viewBoxX + \" \" + viewBoxY + \" \" + svgDims.width + \" \" + svgDims.height);\n }\n };\n render();\n if (recalculateSize) {\n render();\n }\n $timeout(function () { return scope.$digest(); });\n };\n var onMousedown = function (e) {\n isDown = true;\n scope.kbDragStart({ $event: getEvent(e) });\n baseMouse = {\n x: e.screenX + svgDims.scrollX,\n y: e.screenY + svgDims.scrollY\n };\n };\n var onMouseup = function (e) {\n scope.kbDragEnd({ $event: getEvent(e) });\n if (!dragged) {\n var inSvg = false;\n var el = e.target;\n while (el) {\n if (el.tagName == \"svg\") {\n inSvg = true;\n break;\n }\n el = el.parentElement;\n }\n if (inSvg) {\n scope.kbClick({ $event: getEvent(e) });\n e.preventDefault();\n e.stopPropagation();\n }\n }\n else {\n e.preventDefault();\n e.stopPropagation();\n }\n isDown = dragged = false;\n };\n var onMousemove = function (e) {\n if (isDown) {\n scope.kbDragMove({ $event: getEvent(e) });\n if (!scope.disablePan) {\n scope.panX = svgDims.scrollX = (baseMouse.x - e.screenX);\n scope.panY = svgDims.scrollY = (baseMouse.y - e.screenY);\n updateSvg(false);\n }\n var diff = Math.sqrt(Math.abs(((baseMouse.x - e.screenX) ^ 2) + ((baseMouse.y - e.screenY) ^ 2)));\n if (diff > tolerance)\n dragged = true;\n }\n };\n var onWheel = function (event) {\n event.preventDefault();\n if (scope.disableZoom)\n return;\n var difference = 1;\n if (event.deltaY < 0) {\n difference = 1.05;\n }\n else {\n difference = 0.95;\n }\n var oldZoom = svgDims.scale;\n svgDims.scale *= difference;\n scope.zoomLevel = svgDims.scale;\n svgDims.scale = Math.min(Math.max(scope.minZoom, svgDims.scale), scope.maxZoom);\n var zoom = svgDims.scale;\n var scalechange = zoom - oldZoom;\n scope.panX = svgDims.scrollX = svgDims.scrollX + (event.offsetX * scalechange);\n scope.panY = svgDims.scrollY = svgDims.scrollY + (event.offsetY * scalechange);\n //window.console.log(svgDims.scrollX + \", \" + svgDims.scrollY);\n updateSvg(false);\n };\n ngModel.$render = function () {\n var v = ngModel.$viewValue;\n if (!v)\n v = \"\";\n v = v.replace(/url\\((#[^\\)]*)\\)/g, \"url(\" + location.href + \"$1)\");\n scope._html = v; // $v[0].innerHTML;// v? md.Transform(v): null;\n setTimeout(updateSvg, 1);\n };\n element[0].addEventListener(\"pointerdown\", onMousedown);\n document.addEventListener(\"pointerup\", onMouseup);\n element[0].addEventListener(\"pointermove\", onMousemove);\n element[0].addEventListener(\"wheel\", onWheel);\n scope.$on(\"$destroy\", function () {\n element[0].removeEventListener(\"pointerdown\", onMousedown);\n document.removeEventListener(\"pointerup\", onMouseup);\n element[0].removeEventListener(\"pointermove\", onMousemove);\n element[0].removeEventListener(\"wheel\", onWheel);\n });\n };\n return _this;\n }\n KbSvgViewer = __decorate([\n NgComponent({\n token: Token.KbSvgViewer,\n dependencies: [\n Token.$Timeout\n ]\n })\n ], KbSvgViewer);\n return KbSvgViewer;\n }(Directive));\n\n var KbTab = /** @class */ (function (_super) {\n __extends(KbTab, _super);\n function KbTab() {\n var _this = _super.call(this) || this;\n _this.require = \"^kbTabs\";\n _this.replace = true;\n _this.template = Dirs.component(\"kb-tab\");\n _this.restrict = \"AE\";\n _this.scope = {\n value: \"=\",\n label: \"@\",\n invalid: \"=?\",\n selected: \"=?\",\n visible: \"=?\",\n icon: \"@\",\n image: \"@\",\n imageWhenSelected: \"@\"\n };\n _this.transclude = true;\n _this.compile = function (element, atts) {\n if (atts.visible == null)\n atts.visible = \"true\";\n return _this.link;\n };\n _this.link = function (scope, element, atts, tabsCtrl) {\n scope._getElement = function () {\n return element;\n };\n scope._tabsScope = tabsCtrl.scope;\n tabsCtrl.registerTab(scope);\n scope.$watch(\"visible\", function () { return tabsCtrl.tabVisibleChanged(scope); });\n };\n return _this;\n }\n KbTab = __decorate([\n NgComponent({\n token: Token.KbTab,\n dependencies: []\n })\n ], KbTab);\n return KbTab;\n }(Directive));\n\n /**\n * kbTabs\n *\n * kbTabs is utilized by having a parent kb-tabs element, and inside of it a kb-tab-pane (which are the headers)\n * and many kb-tab directives. You can place the kb-tabs-pane and the kb-tabs wherever you like, as long as they\n * are inside the kb-tabs directive. This gives a flexible approach which we can use in any situation.\n *\n * \n * \n * \n * \n * \n *\n * you can remotely control the selected tab by using a two-way binding with selectedTab scope property. This\n * property is looking for the name of the tab.\n *\n */\n var KbTabs = /** @class */ (function (_super) {\n __extends(KbTabs, _super);\n function KbTabs($timeout, $window) {\n var _this = _super.call(this) || this;\n _this.replace = true;\n _this.template = Dirs.component(\"kb-tabs\");\n _this.restrict = \"AE\";\n _this.scope = {\n selectedTab: \"=?\",\n tabChanged: \"&\",\n tabWidth: \"=?\",\n customTabWidth: \"=?\"\n };\n _this.transclude = true;\n // add scope defaults to the compile function\n _this.compile = function (element, atts) {\n };\n _this.controller = [\n \"$scope\",\n \"$element\",\n \"$attrs\",\n \"$transclude\",\n function ($scope, $element, $attrs, $transclude) {\n // set the scope of the tree on it's controller so children can access it\n this.scope = $scope;\n var locked = false; //during tab animations we lock the user from switching tabs\n var firstRun = true;\n var scrollLeft = 0;\n $scope._tabs = [];\n var $container = $element.find(\".kb-tabs__tab-container\");\n var $headers = $element.find(\".kb-tabs__headers\");\n var $pane = $element.find(\".kb-tabs__pane\");\n var $headersContainer = $element.find(\".kb-tabs__headers-container\");\n var selectionLineEl = $element.find(\".kb-tabs__selection-line\")[0];\n $scope._select = function (tab) {\n $scope.selectedTab = tab.value;\n };\n $scope._headerClick = function (e, tab) {\n if (!locked) {\n $scope._select(tab);\n }\n };\n var setSelectedTabScope = function (tab) {\n var oldTab = $scope._selectedTabScope;\n var newTab = tab;\n $scope._selectedTabScope = tab;\n if (oldTab !== newTab) {\n firstRun ? $timeout(function () { return positionSelectionLine(tab); }, 0) : positionSelectionLine(tab);\n scrollSelectedIntoView();\n animateContent(oldTab, newTab);\n if (!firstRun && $scope.tabChanged) { //for the first run, we are just selecting the first visible tab. This should not count as a tabChanged event\n firstRun = false;\n $scope.tabChanged({ oldTab: oldTab ? oldTab.value : null, newTab: newTab ? newTab.value : null });\n }\n firstRun = false;\n }\n };\n var positionSelectionLine = function (tab) {\n var headerEl = $element.find(\"#\".concat(tab.$id))[0];\n if (headerEl) {\n selectionLineEl.style.left = headerEl.offsetLeft + \"px\";\n selectionLineEl.style.width = headerEl.offsetWidth + \"px\";\n }\n };\n var animateContent = function (oldTab, newTab) {\n locked = true;\n var oldTabIndex = $scope._tabs.indexOf(oldTab);\n var newTabIndex = $scope._tabs.indexOf(newTab);\n var $oldTabEl = oldTab && oldTab._getElement();\n var $newTabEl = newTab && newTab._getElement();\n newTab && $newTabEl.css(\"transition\", \"none\");\n if (newTabIndex > oldTabIndex) {\n //oldTab && $oldTabEl.css(\"transform\", \"translate3d(-100%,0,0)\");\n newTab && $newTabEl.css(\"transform\", \"translate3d(100%,0,0)\");\n }\n else {\n newTab && $newTabEl.css(\"transform\", \"translate3d(-100%,0,0)\");\n }\n if (newTab)\n newTab.selected = true;\n setTimeout(function () {\n //animate the height also. \n var currentHeight = oldTab && $oldTabEl.outerHeight();\n newTab && $newTabEl.css(\"position\", \"relative\");\n // oldTab && $oldTabEl.css(\"position\", \"absolute\");\n // $container.height(\"auto\");\n var newHeight = newTab && $newTabEl.outerHeight(); // $container[0].offsetHeight;\n newTab && $newTabEl.css(\"position\", \"absolute\");\n // oldTab && $oldTabEl.css(\"position\", \"relative\");\n $container.height(currentHeight);\n if (newTabIndex > oldTabIndex) {\n oldTab && $oldTabEl.css(\"transform\", \"translate3d(-100%,0,0)\");\n }\n else {\n oldTab && $oldTabEl.css(\"transform\", \"translate3d(100%,0,0)\");\n }\n newTab && $newTabEl.css(\"transition\", \"\");\n newTab && $newTabEl.css(\"transform\", \"translate3d(0,0,0)\");\n $container.height(newHeight);\n // $timeout(() => {\n // }, 0);\n $timeout(function () {\n if (oldTab)\n oldTab.selected = false;\n //on the first run the new tab element might not have existed until now, so we refresh the reference\n $newTabEl = newTab && $element.find(\"#tab-\".concat(newTab.$id));\n newTab && $newTabEl.css(\"position\", \"relative\");\n oldTab && $oldTabEl.css(\"position\", \"absolute\");\n $container.height(\"auto\");\n locked = false;\n }, 300);\n }, 0);\n };\n // all child nodes register themselves with the tree to handle selection and accordion functionality\n this.registerTab = function (tab) {\n $scope._tabs.push(tab);\n tab.$on(\"$destroy\", function (event) {\n $scope._tabs.remove(tab);\n var selectedTab = $scope._tabs.find(function (t) { return t.selected; });\n if (selectedTab) {\n $scope._select(selectedTab);\n $timeout(function () { return positionSelectionLine(selectedTab); }, 0);\n }\n });\n updateSelectedTabScope();\n };\n this.tabVisibleChanged = function (tab) {\n //if the selected tab isn't visible then select the first visible one\n if (tab.selected && !tab.visible) {\n $scope.selectedTab = null;\n $timeout(function () {\n updateSelectedTabScope();\n });\n }\n else {\n $timeout(function () {\n if ($scope._selectedTabScope)\n positionSelectionLine($scope._selectedTabScope);\n });\n }\n };\n var updateSelectedTabScope = function () {\n if (!$scope.selectedTab && $scope._tabs.some(function (t) { return t.visible; })) {\n $scope.selectedTab = $scope._tabs.find(function (t) { return t.visible; }).value;\n }\n for (var _i = 0, _a = $scope._tabs; _i < _a.length; _i++) {\n var tab = _a[_i];\n if (tab.value === $scope.selectedTab) {\n setSelectedTabScope(tab);\n break;\n }\n }\n };\n // if the consumer changes the selected item, we update the selected node\n $scope.$watch(\"selectedTab\", function (newVal, oldVal) {\n updateSelectedTabScope();\n });\n $scope.$watch(\"tabWidth\", function () {\n if ($scope._selectedTabScope)\n $timeout(function () { return positionSelectionLine($scope._selectedTabScope); }, 300);\n });\n $scope.$watch(\"customTabWidth\", function () {\n if ($scope._selectedTabScope)\n $timeout(function () { return positionSelectionLine($scope._selectedTabScope); }, 300);\n });\n var updatePagination = function () {\n var containerWidth = $headersContainer.width();\n var headersWidth = $headers.width();\n var paneWidth = $pane.width();\n $scope._paged = (headersWidth > paneWidth);\n $scope._pageNextVisible = (headersWidth > containerWidth + scrollLeft);\n $scope._pagePrevVisible = (scrollLeft > 0);\n };\n var scrollSelectedIntoView = function () {\n var headerEl = $element.find(\"#\".concat($scope._selectedTabScope.$id))[0];\n if (headerEl) {\n var elemLeft = headerEl.offsetLeft;\n var elemRight = elemLeft + headerEl.offsetWidth;\n var containerWidth = $headersContainer[0].clientWidth;\n if (elemLeft - scrollLeft < 0) {\n setScroll(elemLeft);\n }\n else if (elemRight > scrollLeft + containerWidth) {\n setScroll(elemRight - containerWidth);\n }\n }\n };\n $scope._scrollNext = function () {\n setScroll(scrollLeft + $headersContainer.width());\n };\n $scope._scrollPrev = function () {\n setScroll(scrollLeft - $headersContainer.width());\n };\n var setScroll = function (val) {\n scrollLeft = fixScroll(val);\n $headers.css(\"transform\", \"translateX(\".concat(-scrollLeft, \"px)\"));\n updatePagination();\n };\n var scroll = function (e) {\n if ($scope._paged) {\n e.preventDefault();\n setScroll(scrollLeft - e.wheelDelta);\n $scope.$digest();\n }\n };\n var fixScroll = function (value) {\n if (!$scope._paged)\n return 0;\n if (value < 0)\n return 0;\n var headersWidth = $headers.width();\n var containerWidth = $headersContainer.width();\n if (value > headersWidth - containerWidth)\n return headersWidth - containerWidth;\n return value;\n };\n var windowResize = function (e) {\n updatePagination();\n setScroll(scrollLeft);\n $scope.$digest();\n };\n $headersContainer[0].addEventListener(\"mousewheel\", scroll);\n $($window).on(\"resize\", windowResize);\n $timeout(function () {\n updatePagination();\n }, 0);\n $scope.$on(\"$destroy\", function () {\n if ($headers && $headers.length)\n $headers[0].removeEventListener(\"mousewheel\", scroll);\n $($window).off(\"resize\", windowResize);\n });\n }\n ];\n return _this;\n }\n KbTabs = __decorate([\n NgComponent({\n token: Token.KbTabs,\n dependencies: [\n Token.$Timeout,\n Token.$Window\n ]\n })\n ], KbTabs);\n return KbTabs;\n }(Directive));\n\n var KbTextbox = /** @class */ (function (_super) {\n __extends(KbTextbox, _super);\n function KbTextbox($timeout) {\n var _this = _super.call(this, $timeout) || this;\n _this.scope = _tools.Utils.extend(_this.scope, {\n mask: \"=?\"\n });\n _this.template = Dirs.component(\"kb-textbox\");\n _this.controller = [\n \"$scope\",\n \"$element\",\n \"$attrs\",\n function ($scope, $element, $attrs) {\n $scope._maskConfig = {\n mask: function () {\n switch ($scope.mask) {\n case enums.eMaskType.phone:\n return ['(', /[1-9]/, /\\d/, /\\d/, ')', ' ', /\\d/, /\\d/, /\\d/, '-', /\\d/, /\\d/, /\\d/, /\\d/];\n case enums.eMaskType.zipCode:\n return [/\\d/, /\\d/, /\\d/, /\\d/, /\\d/];\n default:\n return false;\n }\n },\n placeholderChar: '\\u2000',\n guide: true,\n keepCharPositions: false,\n showMask: false\n };\n }\n ];\n _this.link = function (scope, element, atts, controllers) {\n _this.kbInputLinkFn(scope, element, atts, controllers);\n //need to fully blur field on ESC press\n element.on(\"keydown\", function (e) {\n if (e.key == 'Escape') {\n element.find(\"input\").trigger('blur');\n element.find(\"textarea\").trigger('blur');\n }\n });\n };\n return _this;\n }\n KbTextbox = __decorate([\n NgComponent({\n token: Token.KbTextbox,\n dependencies: [\n Token.$Timeout\n ]\n })\n ], KbTextbox);\n return KbTextbox;\n }(KbInput));\n\n var KbTextarea = /** @class */ (function (_super) {\n __extends(KbTextarea, _super);\n function KbTextarea($timeout) {\n var _this = _super.call(this, $timeout) || this;\n _this.restrict = \"E\";\n _this.replace = true;\n _this.template = Dirs.component(\"kb-textarea\");\n return _this;\n }\n KbTextarea = __decorate([\n NgComponent({\n token: Token.KbTextarea,\n dependencies: [\n Token.$Timeout\n ]\n })\n ], KbTextarea);\n return KbTextarea;\n }(KbTextbox));\n\n var KbToggle = /** @class */ (function (_super) {\n __extends(KbToggle, _super);\n function KbToggle($timeout) {\n var _this = _super.call(this, $timeout) || this;\n _this.template = Dirs.component(\"kb-toggle\");\n return _this;\n }\n KbToggle = __decorate([\n NgComponent({\n token: Token.KbToggle,\n dependencies: [\n Token.$Timeout\n ]\n })\n ], KbToggle);\n return KbToggle;\n }(KbCheckbox));\n\n var KbTooltip = /** @class */ (function (_super) {\n __extends(KbTooltip, _super);\n function KbTooltip($timeout) {\n var _this = _super.call(this) || this;\n _this.restrict = \"EA\";\n _this.scope = {\n label: \"=?\",\n media: \"=?\",\n helpUrl: \"=?\",\n desc: \"=?\"\n };\n _this.replace = true;\n _this.transclude = true;\n _this.template = Dirs.component(\"kb-tooltip\");\n _this.link = function (scope, element, atts) {\n };\n return _this;\n }\n KbTooltip = __decorate([\n NgComponent({\n token: Token.KbTooltip,\n dependencies: [\n Token.$Timeout\n ]\n })\n ], KbTooltip);\n return KbTooltip;\n }(Directive));\n\n /**\n * kbTransclude\n *\n * This is an alternative to ngTransclude, which allows you to select which\n * scope the transcluded content in the directive should have.\n * This is usefule because the standard ngTransclude will always create\n * a child scope of the outer scope where the directive is used.\n * Which stops us from using ng-repeat type directives where the transcluded\n * content accesses something like an item property that is coming\n * from the ng-repeat inside the directive template.\n * See here for details: https://github.com/angular/angular.js/issues/7874#issuecomment-53450394\n * usage:\n *\n *
\n *
\n */\n var KbTransclude = /** @class */ (function (_super) {\n __extends(KbTransclude, _super);\n function KbTransclude() {\n var _this = _super.call(this) || this;\n _this.restrict = \"EAC\";\n _this.link = function (scope, element, atts, ctrl, $transclude) {\n if (!$transclude) {\n throw new Error(\"Illegal use of ngTransclude directive in the template! \" +\n \"No parent directive that requires a transclusion found.\");\n }\n var iScopeType = atts.kbTransclude || \"outer\";\n var slotName = atts.kbTranscludeSlot; //slot name for multi-slot transclusion\n var iChildScope;\n switch (iScopeType) {\n // this is the default of angular 1.3+... \n // outer is the controller scope where the directive was originally called from\n case \"outer\":\n $transclude(function (clone) {\n element.empty();\n element.append(clone);\n }, null, slotName);\n break;\n case \"parent\": // this will use the scope of the directive\n $transclude(scope, function (clone) {\n element.empty();\n element.append(clone);\n }, null, slotName);\n break;\n case \"child\": // this will create a new child scope of the directive scope\n iChildScope = scope.$new();\n $transclude(iChildScope, function (clone) {\n element.empty();\n element.append(clone);\n element.on(\"$destroy\", function () {\n if (iChildScope) {\n iChildScope.$destroy();\n }\n });\n }, null, slotName);\n break;\n }\n scope.$on(\"$destroy\", function () {\n if (iChildScope) {\n iChildScope.$destroy();\n }\n });\n };\n return _this;\n }\n KbTransclude = __decorate([\n NgComponent({\n token: Token.KbTransclude,\n dependencies: []\n })\n ], KbTransclude);\n return KbTransclude;\n }(Directive));\n\n var KbTreeNode = /** @class */ (function (_super) {\n __extends(KbTreeNode, _super);\n function KbTreeNode($timeout) {\n var _this = _super.call(this) || this;\n _this.require = [\"^kbTree\", \"^^?kbTreeNode\", \"kbTreeNode\"];\n _this.replace = true;\n _this.template = Dirs.component(\"kb-tree-node\");\n _this.restrict = \"AE\";\n _this.scope = {\n label: \"@\",\n selectable: \"=?\",\n expanded: \"=?\",\n item: \"=?\",\n image: \"@\",\n imageWhenSelected: \"@\",\n icon: \"@\",\n valid: \"=?\",\n checked: \"=?\",\n checkedChanged: \"&\",\n labelTemplate: \"@\",\n childTemplate: \"@\",\n hasChildren: \"=?\"\n };\n _this.transclude = true;\n _this.controller = [\n \"$scope\",\n \"$element\",\n \"$attrs\",\n \"$transclude\",\n \"$templateCache\",\n Token.$Compile.key,\n function ($scope, $element, $attrs, $transclude, $templateCache, $compile) {\n this.scope = $scope;\n var timeouts = [];\n var treeController = $element.controller(\"kbTree\");\n // let loadAllNodes = false;\n var childTemplateProcessed = false;\n // if (treeController) loadAllNodes = treeController.scope.loadAllNodes;\n $scope._children = [];\n // $scope._childrenValid = true;\n this.registerNode = function (node) {\n $scope._children.push(node);\n var off = node.$on(\"$destroy\", function (event) {\n $scope._children.remove(node);\n off();\n });\n };\n // $scope._calculateChildrenValid = () => {\n // for (var i = 0; i < $scope._children.length; i++) {\n // var node = $scope._children[i];\n // if (!node.valid || !node._childrenValid) {\n // $scope._childrenValid = false;\n // return;\n // }\n // }\n // $scope._childrenValid = true;\n // };\n $scope._getElement = function () {\n return $element;\n };\n var $headerElem;\n $scope._getHeaderElement = function () {\n if (!$headerElem)\n $headerElem = $element.find(\">.kb-tree__header\");\n return $headerElem;\n };\n $scope._calculateIcon = function () {\n if (!$scope.valid) {\n $scope._icon = \"error\";\n // } else if (!$scope._childrenValid) {\n // $scope._icon = \"childError\";\n }\n else if ($scope.icon) {\n $scope._icon = $scope.icon;\n }\n else {\n $scope._icon = null;\n }\n };\n $scope._getAncestorNodes = function (includeThis) {\n if (includeThis === void 0) { includeThis = true; }\n var ancestorNodes = (includeThis ? [$scope] : []);\n var parent = $scope;\n do {\n parent = parent._parentNode;\n if (parent) {\n ancestorNodes.push(parent);\n }\n } while (parent);\n return ancestorNodes;\n };\n // if a label template was passed in then get it from the template cache\n if ($scope.labelTemplate) {\n var templateHtml = $templateCache.get($scope.labelTemplate);\n if (!templateHtml) {\n throw \"Could not find template for \" + $scope.labelTemplate;\n }\n var $template = angular.element(templateHtml);\n // compile the template\n var compiled = $compile($template, $transclude);\n // append it to the label\n $element.find(\".kb-tree__label\").empty().append($template);\n // now link it to the parent scope(we don't want this scope because it's an isolate scope)\n compiled($scope.$parent);\n }\n var childScope;\n var addChildTemplate = function () {\n if (!childTemplateProcessed) {\n // if a child template was provided, then use that instead of the transclusion content\n if ($scope.childTemplate) {\n var templateHtml = $templateCache.get($scope.childTemplate);\n if (!templateHtml) {\n throw \"Could not find template for \" + $scope.childTemplate;\n }\n var $template = angular.element(templateHtml);\n // compile the template\n var compiled = $compile($template, $transclude);\n // append it to the label\n $element.find(\".kb-tree__node-children\").empty().append($template);\n childScope = $scope.$parent.$new();\n // now link it to the parent scope(we don't want this scope because it's an isolate scope)\n compiled(childScope);\n }\n else { // no child template was provided so use the content of the directive\n $transclude(function (clone, cloneScope) {\n childScope = cloneScope;\n $element.find(\".kb-tree__node-children\").empty().append(clone);\n });\n }\n childTemplateProcessed = true;\n }\n };\n // if (loadAllNodes) {\n // addChildTemplate();\n // }\n this.updateChildTemplate = function () {\n // if (!loadAllNodes) {\n if ($scope.expanded) {\n addChildTemplate();\n }\n // }\n };\n $scope.$on(\"$destroy\", function () {\n timeouts.forEach(function (t) { return $timeout.cancel(t); });\n if (childScope)\n childScope.$destroy();\n });\n }\n ];\n _this.compile = function (element, atts) {\n if (angular.isUndefined(atts.selectable)) {\n atts.selectable = \"true\";\n }\n if (angular.isUndefined(atts.valid)) {\n atts.valid = \"true\";\n }\n if (angular.isUndefined(atts.childrenValid)) {\n atts.childrenValid = \"true\";\n }\n return _this.link;\n };\n _this.link = function (scope, element, atts, controllers) {\n var timeouts = [];\n var treeController = controllers[0];\n var parentController = controllers.length > 1 ? controllers[1] : null;\n var thisController = controllers[2];\n // get parent scopes to use for selection and expansion\n var treeScope = treeController.scope;\n scope._treeScope = treeScope;\n // register the node with the parent kbTree\n treeController.registerNode(scope);\n if (parentController) {\n scope._parentNode = parentController.scope;\n parentController.registerNode(scope);\n }\n // if no data item was given for the node, then we create one\n if (!scope.item) {\n scope.item = { id: _tools.Utils.shortId() };\n }\n var updateExpanded = function () {\n if (treeScope.expandable) ;\n else {\n scope.expanded = true;\n }\n };\n scope.$watch(\"expanded\", function (newValue, oldValue) {\n // update the child template when expanded is changed... \n // this is what makes kbTree do virtual rendering of nodes to increase performance\n thisController.updateChildTemplate();\n treeController.refreshSelectionLine();\n });\n var select = function () {\n // select the item if it's selectable\n if (treeScope.selectable && scope.selectable) {\n // set the selected item on the tree so it can be bound to by controllers\n treeScope._selectedNode = scope;\n treeScope.selectedItem = scope.item;\n }\n };\n scope._arrowClick = function ($event) {\n $event.stopPropagation();\n scope.expanded = !scope.expanded;\n updateExpanded();\n };\n scope._nodeClick = function ($event) {\n // $event.stopPropagation();\n // toggle expanded\n if (treeScope.accordion) {\n // only collapse when this node is already selected\n if (treeScope._selectedNode == scope && scope.expanded) {\n scope.expanded = false;\n }\n else {\n scope.expanded = true;\n }\n updateExpanded();\n }\n select();\n };\n scope._checkedChanged = function (item) {\n $timeout(function () {\n scope.checkedChanged({ item: item });\n }, 0);\n };\n // calculate the levels which is used for margins\n scope._level = function () {\n return scope._getAncestorNodes().length - 1;\n };\n updateExpanded();\n // watch for changes in validity to recalculate the icon\n scope.$watch(\"valid\", function (newValue, oldValue) {\n if (newValue !== oldValue) {\n // if (parentController) parentController.scope._calculateChildrenValid();\n scope._calculateIcon();\n }\n });\n // watch for changes to the icon provided by the consumer to recalculate\n scope.$watch(\"icon\", function (newValue, oldValue) {\n scope._calculateIcon();\n });\n // scope.$watch(\"_childrenValid\", (newValue, oldValue) => {\n // if (newValue !== oldValue) {\n // if (parentController) parentController.scope._calculateChildrenValid();\n // scope._calculateIcon();\n // }\n // });\n if (treeScope.dragDrop) {\n var el_1 = element[0];\n var getDropPosition_1 = function (e, allow) {\n var elementPosition = element.offset();\n var elementHeight = element.find(\">.kb-tree__header\").outerHeight(true);\n var mouseRelativeToElementY = e.clientY - elementPosition.top;\n var dropPosition;\n if (allow == \"any\") {\n if (mouseRelativeToElementY < (elementHeight / 4)) {\n dropPosition = \"above\";\n }\n else if (mouseRelativeToElementY > (elementHeight * .75)) {\n dropPosition = \"below\";\n }\n else {\n dropPosition = \"in\";\n }\n }\n else if (allow == \"sibling\") {\n if (mouseRelativeToElementY < (elementHeight / 2)) {\n dropPosition = \"above\";\n }\n else {\n dropPosition = \"below\";\n }\n }\n else if (allow == \"child\") {\n dropPosition = \"in\";\n }\n return dropPosition;\n };\n el_1.ondragstart = function (e) {\n treeScope._dragNode = scope;\n e.dataTransfer.effectAllowed = \"move\";\n e.dataTransfer.setData(\"text/plain\", \"node\");\n e.stopPropagation();\n timeouts.push($timeout(function () {\n select();\n }));\n };\n el_1.ondragover = function (e) {\n var allow;\n if (treeScope.allowDrop()) {\n allow = treeScope.allowDrop()(scope.item, treeScope._dragNode.item);\n }\n if (allow === \"any\" || allow === \"child\" || allow == \"sibling\") {\n // tell the drag drop system the drop is ok by preventingDefault\n e.preventDefault();\n }\n else {\n e.dataTransfer.dropEffect = \"none\";\n }\n var dropPosition = getDropPosition_1(e, allow);\n element.toggleClass(\"kb-tree--dropping-child\", ((allow == \"child\" || allow == \"any\") && dropPosition == \"in\"));\n element.toggleClass(\"kb-tree--dropping-sibling-below\", ((allow == \"sibling\" || allow == \"any\") && dropPosition == \"below\"));\n element.toggleClass(\"kb-tree--dropping-sibling-above\", ((allow == \"sibling\" || allow == \"any\") && dropPosition == \"above\"));\n // e.dataTransfer.setData(\"text\", dropPosition);\n e.stopPropagation();\n treeController.setCurrentDragTarget(e.currentTarget);\n };\n // el.ondragenter = e => {\n // console.log({ event: \"dragenter\", el: e.currentTarget });\n // };\n // el.ondragleave = e => {\n // if (e.currentTarget === currentDragTarget) {\n // removeDropClasses();\n // e.stopPropagation();\n // console.log({ event: \"dragleave\", el: e.currentTarget });\n // } \n // };\n el_1.ondrop = function (e) {\n if (e.preventDefault)\n e.preventDefault();\n if (e.stopPropagation)\n e.stopPropagation();\n treeController.removeDropClasses(element);\n timeouts.push($timeout(function () {\n if (treeScope._dragNode) {\n var target = scope.item;\n var source = treeScope._dragNode.item;\n if (target != source) {\n var allow = treeScope.allowDrop()(target, source);\n var dropPosition = getDropPosition_1(e, allow);\n var targetParent = scope._parentNode ? scope._parentNode.item : undefined;\n var sourceParent = treeScope._dragNode._parentNode ?\n treeScope._dragNode._parentNode.item\n : undefined;\n treeScope.dropped()(target, source, targetParent, sourceParent, dropPosition);\n treeScope._dragNode = undefined;\n // if we just dropped in this node, then expand it\n if (dropPosition == \"in\") {\n scope.expanded = true;\n updateExpanded();\n }\n }\n }\n }));\n };\n el_1.ondragend = function (e) {\n timeouts.push($timeout(function () {\n treeScope._dragNode = undefined;\n treeController.setCurrentDragTarget(null);\n }));\n };\n scope.$on(\"$destroy\", function () {\n el_1.ondragstart = null;\n el_1.ondragover = null;\n el_1.ondragleave = null;\n el_1.ondrop = null;\n el_1.ondragend = null;\n scope._parentNode = null;\n treeController = null;\n treeScope = null;\n timeouts.forEach(function (t) { return $timeout.cancel(t); });\n });\n }\n };\n return _this;\n }\n KbTreeNode = __decorate([\n NgComponent({\n token: Token.KbTreeNode,\n dependencies: [\n Token.$Timeout\n ]\n })\n ], KbTreeNode);\n return KbTreeNode;\n }(Directive));\n\n /**\n * KbTree\n *\n * kbTree can be used in several different ways.\n * If you have a hierarchy of like objects that infinitely nest, you can use it like so:\n *\n * \n *\n * \n * \n * \n * \n *\n * in this case you are providing a child template to the tree-node directive,\n * which refers to itself. In this way we achieve\n * infinite nesting.\n *\n * If you do NOT need infinite nesting, then you can just add tree-nodes as content\n * of other tree-nodes, while NOT providing\n * a child template. Like so:\n *\n * <\n * \n * \n * \n * \n * \n *\n */\n var KbTree = /** @class */ (function (_super) {\n __extends(KbTree, _super);\n function KbTree() {\n var _this = _super.call(this) || this;\n _this.replace = true;\n _this.template = Dirs.component(\"kb-tree\");\n _this.restrict = \"AE\";\n _this.scope = {\n selectedItem: \"=?\",\n accordion: \"=?\",\n skin: \"@\",\n selectable: \"=?\",\n expandable: \"=?\",\n dragDrop: \"=?\",\n allowDrop: \"&?\",\n dropped: \"&?\",\n animation: \"@\",\n // loadAllNodes: \"=?\",\n horizontal: \"=?\",\n selectionStyle: \"=?\",\n selectionClass: \"=?\",\n selectionLineColor: \"=?\",\n tabWidth: \"=?\"\n // control: \"=?\"\n };\n _this.transclude = true;\n // add scope defaults to the compile function\n _this.compile = function (element, atts) {\n if (!angular.isDefined(atts.selectable))\n atts.selectable = \"true\";\n if (!angular.isDefined(atts.expandable))\n atts.expandable = \"true\";\n if (!angular.isDefined(atts.selectionStyle))\n atts.selectionStyle = \"'background'\";\n if (!angular.isDefined(atts.selectionLineColor))\n atts.selectionLineColor = \"'accent'\";\n if (!angular.isDefined(atts.tabWidth))\n atts.tabWidth = \"'auto'\";\n };\n _this.controller = [\n \"$scope\",\n \"$element\",\n \"$attrs\",\n \"$transclude\",\n function ($scope, $element, $attrs, $transclude) {\n var _this = this;\n // set the scope of the tree on it's controller so children can access it\n this.scope = $scope;\n $scope._nodes = [];\n // $scope.control = $scope.control || {};\n // $scope.control.expandToNode = (item) => {\n // $scope._nodes.forEach(n => setChildrenValid(n));\n // };\n // all child nodes register themselves with the tree to handle selection and accordion functionality\n this.registerNode = function (node) {\n $scope._nodes.push(node);\n var off = node.$on(\"$destroy\", function (event) {\n $scope._nodes.remove(node);\n off();\n });\n };\n this.setCurrentDragTarget = function (el) {\n if (el !== $scope._currentDragTarget && $scope._currentDragTarget) {\n _this.removeDropClasses($($scope._currentDragTarget));\n console.log({ event: \"currentDragChanged\", el: el });\n }\n $scope._currentDragTarget = el;\n };\n this.removeDropClasses = function ($target) {\n $target.removeClass(\"kb-tree--dropping-child\");\n $target.removeClass(\"kb-tree--dropping-sibling-below\");\n $target.removeClass(\"kb-tree--dropping-sibling-above\");\n };\n var updateSelectedNode = function () {\n for (var _i = 0, _a = $scope._nodes; _i < _a.length; _i++) {\n var node = _a[_i];\n if (node.item === $scope.selectedItem) {\n var origSelected = $scope._selectedNode;\n $scope._selectedNode = node;\n scrollToSelectedNode();\n refreshSelectionLine();\n // expand all parent nodes when a node is selected\n node._getAncestorNodes(false).forEach(function (n) { return n.expanded = true; });\n break;\n }\n }\n };\n // if the consumer changes the selected item, we update the selected node\n $scope.$watch(\"selectedItem\", function () {\n updateSelectedNode();\n });\n // nodes might be added after the selectedItem is set by the consumer, so\n // we need to refind the selected node when the nodes collection changes\n $scope.$watchCollection(\"_nodes\", function () {\n if (!$scope._selectedNode) {\n updateSelectedNode();\n }\n });\n $scope.$watch(\"expandable\", function () {\n if (!$scope.expandable) {\n $scope._nodes.forEach(function (n) { return expandNodeAndChildren(n); });\n refreshSelectionLine();\n }\n });\n $scope.$watch(\"horizontal\", function () {\n setTimeout(function () { return refreshSelectionLine(); }, 0);\n });\n $scope.$watch(\"selectionStyle\", function () {\n setTimeout(function () { return refreshSelectionLine(); }, 0);\n });\n $scope.$watch(\"tabWidth\", function () {\n setTimeout(function () { return refreshSelectionLine(); }, 0);\n });\n var expandNodeAndChildren = function (node) {\n node.expanded = true;\n node._children.forEach(function (child) { return expandNodeAndChildren(child); });\n };\n var scrollToSelectedNode = function () {\n setTimeout(function () {\n if ($scope._selectedNode) {\n var $node = $scope._selectedNode._getHeaderElement();\n if ($node && $node.length) {\n _tools.Utils.scrollIntoView({ elem: $node[0], mode: _tools.eScrollMode.nearest, animate: true, horizontal: $scope.horizontal });\n }\n }\n }, 0);\n };\n var $selectionLine;\n var refreshSelectionLine = this.refreshSelectionLine = function () {\n if ($scope._selectedNode && $scope.selectionStyle && $scope.selectionStyle.isEqual(\"line\")) {\n if (!$selectionLine || !$selectionLine.length) {\n $selectionLine = $('
', {\n class: \"kb-tree__selection-line\",\n appendTo: $element\n });\n }\n var $node = $scope._selectedNode._getElement();\n var nodeEl = $node.find(\".kb-tree__header\").first()[0];\n if ($scope.horizontal) {\n $selectionLine.css({ left: nodeEl.offsetLeft, width: nodeEl.offsetWidth, bottom: 0, height: \"2px\", top: \"auto\" });\n }\n else {\n $selectionLine.css({ top: nodeEl.offsetTop, height: nodeEl.offsetHeight, left: 0, width: \"2px\", bottom: \"auto\" });\n }\n }\n else {\n if ($selectionLine)\n $selectionLine.remove();\n $selectionLine = null;\n }\n };\n }\n ];\n return _this;\n }\n KbTree = __decorate([\n NgComponent({\n token: Token.KbTree,\n dependencies: []\n })\n ], KbTree);\n return KbTree;\n }(Directive));\n\n var KbUiObject = /** @class */ (function (_super) {\n __extends(KbUiObject, _super);\n function KbUiObject() {\n var _this = _super.call(this) || this;\n _this.replace = true;\n _this.restrict = \"E\";\n _this.scope = false;\n _this.template = Dirs.component(\"kb-ui-object\");\n return _this;\n }\n KbUiObject = __decorate([\n NgComponent({\n token: Token.KbUiObject,\n })\n ], KbUiObject);\n return KbUiObject;\n }(Directive));\n\n var KbUpload = /** @class */ (function (_super) {\n __extends(KbUpload, _super);\n function KbUpload($timeout, uploadService, dialogService, storageService) {\n var _this = _super.call(this, $timeout) || this;\n _this.restrict = \"EA\";\n _this.scope = _tools.Utils.extend(_this.scope, {\n upload: \"&\",\n cleared: \"&\",\n accept: \"@\"\n });\n _this.template = Dirs.component(\"kb-upload\");\n _this.link = function (scope, element, atts) {\n scope._fileName = function () {\n if (atts.guid && scope.ngModel && scope.ngModel.path) {\n return scope.ngModel.path.substr(scope.ngModel.path.indexOf(\"_\") + 1);\n }\n else {\n return scope.ngModel.path;\n }\n };\n scope._clear = function () {\n dialogService.confirm(\"Are you sure you want to remove this upload?\", function () {\n scope.ngModel.path = null;\n scope.ngModel.assetId = null;\n scope._thumbnailDataUrl = \"\";\n scope.ngChange();\n scope.cleared();\n });\n };\n scope._btnClick = function () {\n uploadService.promptUserToChooseFile(scope.accept).then(function (file) {\n if (!scope.ngModel)\n scope.ngModel = { path: null, assetId: null };\n scope.ngModel.path = file.name;\n var uploadPromise = scope.upload({ file: file }).then(function () {\n // only trigger valuechange when upload is done so the rules have\n // the file(especially important for images being uploaded to the scene)\n scope.ngChange();\n });\n // show a thumbnail of the image\n if (file.type.match(\"image.*\")) {\n scope._thumbnailDataUrl = storageService.getAssetUrl(\"images/spinning_circle.gif\");\n var reader_1 = new FileReader();\n reader_1.onloadend = function () {\n scope._thumbnailDataUrl = reader_1.result;\n reader_1.onloadend = null;\n };\n reader_1.readAsDataURL(file);\n }\n else {\n scope._thumbnailDataUrl = null;\n }\n });\n };\n };\n return _this;\n }\n KbUpload = __decorate([\n NgComponent({\n token: Token.KbUpload,\n dependencies: [\n Token.$Timeout,\n Token.UploadService,\n Token.DialogService,\n Token.StorageService\n ]\n })\n ], KbUpload);\n return KbUpload;\n }(KbInput));\n\n /**\n * For showing validation messages of a configurator\n */\n var KbValidationMessages = /** @class */ (function (_super) {\n __extends(KbValidationMessages, _super);\n function KbValidationMessages() {\n var _this = _super.call(this) || this;\n _this.restrict = \"EA\";\n _this.template = Dirs.component(\"kb-validation-messages\", exports.eBundle.app);\n _this.scope = {\n ngModel: \"=?\",\n messageClicked: \"&\",\n hideAutoValidation: \"=?\",\n autoValidation: \"=?\"\n };\n _this.replace = true;\n _this.link = function (scope, element, atts) {\n scope._toggleAutoValidation = function () {\n scope.autoValidation = !scope.autoValidation;\n };\n scope._getTitle = function () {\n var title = \"\";\n if (!scope.ngModel || scope.ngModel.length == 0) {\n title = loc.noerrors;\n }\n else {\n var errors = scope.ngModel.filter(function (m) { return m.messageType == enums.eValidationType.error; });\n var warnings = scope.ngModel.filter(function (m) { return m.messageType == enums.eValidationType.warning; });\n if (errors.length) {\n title += errors.length + \" \" + (errors.length > 1 ? loc.errors : loc.error);\n }\n if (errors.length && warnings.length) {\n title += \" / \";\n }\n if (warnings.length) {\n title += warnings.length + \" \" + (warnings.length > 1 ? loc.warnings : loc.warning);\n }\n }\n return title;\n };\n };\n return _this;\n }\n KbValidationMessages = __decorate([\n NgComponent({\n token: Token.KbValidationMessages\n })\n ], KbValidationMessages);\n return KbValidationMessages;\n }(Directive));\n\n var AssetFilter = /** @class */ (function () {\n function AssetFilter(storageService) {\n return (function (relativePath) {\n return storageService.getAssetUrl(relativePath);\n });\n }\n AssetFilter = __decorate([\n NgFilter({\n token: Token.AssetFilter,\n dependencies: [\n Token.StorageService\n ]\n })\n ], AssetFilter);\n return AssetFilter;\n }());\n\n var BytesFilter = /** @class */ (function () {\n function BytesFilter() {\n return (function (bytes, precision) {\n if (isNaN(parseFloat(bytes)) || !isFinite(bytes))\n return \"-\";\n if (bytes == 0)\n return \"0 KB\";\n var units = [\"bytes\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\"];\n var n = Math.floor(Math.log(bytes) / Math.log(1024));\n if (typeof precision === \"undefined\")\n precision = (n ? 1 : 0);\n return (bytes / Math.pow(1024, Math.floor(n))).toFixed(precision) + \" \" + units[n];\n });\n }\n BytesFilter = __decorate([\n NgFilter({\n token: Token.BytesFilter,\n dependencies: []\n })\n ], BytesFilter);\n return BytesFilter;\n }());\n\n // declare module \"angular\" {\n // interface IFilterService {\n // (name: \"enum\"): IEnumFilter;\n // }\n // }\n /**\n * takes an enum type name and returns an array of name/value pairs\n * that have the localization representing the enum value as the name\n * and the value as the string value for the enum\n */\n var EnumFilter = /** @class */ (function () {\n function EnumFilter(kbService) {\n return (function (enumName, localize) {\n if (localize === void 0) { localize = true; }\n var enumType = enums__namespace[enumName];\n var results = [];\n for (var i in enumType) {\n var locTitle = enumType[i];\n var locDesc = null;\n if (localize) {\n // get the localized value for the enum value. This is convention based\n var resxName = enumName + \"_\" + enumType[i] + \"_title\";\n locTitle = kbService.loc(resxName);\n // if we still have the resx name, then try to see if there is already a matching word\n if (locTitle.isEqual(resxName)) {\n var low = enumType[i].toLowerCase();\n if (loc.hasOwnProperty(low)) {\n locTitle = kbService.loc(low);\n }\n }\n resxName = enumName + \"_\" + enumType[i] + \"_desc\";\n locDesc = kbService.loc(resxName);\n }\n results.push({ name: locTitle, value: enumType[i], desc: locDesc });\n }\n return results;\n });\n }\n EnumFilter = __decorate([\n NgFilter({\n token: Token.EnumFilter,\n dependencies: [\n Token.KbService\n ]\n })\n ], EnumFilter);\n return EnumFilter;\n }());\n\n // declare module \"angular\" {\n // interface IFilterService {\n // (name: \"fileIcon\"): IFileIconFilter;\n // }\n // }\n var FileIconFilter = /** @class */ (function () {\n function FileIconFilter($filter, storageService) {\n this.$filter = $filter;\n this.storageService = storageService;\n return (function (filepath, root) {\n if (root === void 0) { root = \"media\"; }\n var ext = filepath && filepath.substr(filepath.lastIndexOf(\".\"));\n if (ext)\n ext = ext.toLowerCase();\n var imageName = \"\";\n switch (ext) {\n case \".docx\":\n case \".doc\":\n imageName = \"docx.png\";\n break;\n case \".xlsx\":\n case \".xls\":\n imageName = \"xlsx.png\";\n break;\n case \".txt\":\n imageName = \"txt.png\";\n break;\n case \".xml\":\n imageName = \"xml.png\";\n break;\n case \".pdf\":\n imageName = \"pdf.png\";\n break;\n case \".sldasm\":\n imageName = \"sldasm.png\";\n break;\n case \".sldprt\":\n imageName = \"sldprt.png\";\n break;\n case \".slddrw\":\n imageName = \"slddrw.png\";\n break;\n case \".iam\":\n imageName = \"default.png\";\n break;\n case \".ipt\":\n imageName = \"default.png\";\n break;\n case \".idw\":\n imageName = \"default.png\";\n break;\n case \".dwg\":\n imageName = \"dwg.png\";\n break;\n case \".dxf\":\n imageName = \"dxf.png\";\n break;\n case \".webm\":\n case \".ogv\":\n case \".mp4\":\n case \".3gp\":\n case \".avi\":\n imageName = \"video.png\";\n break;\n case \".png\":\n case \".gif\":\n case \".jpg\":\n case \".bmp\":\n if (root == \"media\") {\n return $filter(\"thumb\")(filepath);\n }\n else {\n imageName = \"image.png\";\n break;\n }\n case \".zip\":\n imageName = \"zip.png\";\n break;\n default:\n imageName = \"default.png\";\n break;\n }\n return storageService.getAssetUrl(\"images/file_icons/\" + imageName);\n });\n }\n FileIconFilter = __decorate([\n NgFilter({\n token: Token.FileIconFilter,\n dependencies: [\n Token.$Filter,\n Token.StorageService\n ]\n })\n ], FileIconFilter);\n return FileIconFilter;\n }());\n\n // declare module \"angular\" {\n // interface IFilterService {\n // (name: \"fileId\"): IFileIdFilter;\n // }\n // }\n /**\n * Takes file name and strips non alpha-numeric characters out to make it compatible with\n * HTML ids, for instance.\n */\n var FileIdFilter = /** @class */ (function () {\n function FileIdFilter() {\n return (function (fileName) {\n return fileName.replace(/[^A-Z0-9]/gi, \"_\");\n });\n }\n FileIdFilter = __decorate([\n NgFilter({\n token: Token.FileIdFilter,\n dependencies: []\n })\n ], FileIdFilter);\n return FileIdFilter;\n }());\n\n var FxConvertFilter = /** @class */ (function () {\n function FxConvertFilter($filter, kbService) {\n return (function (value, currencyCode, precision) {\n if (value == null)\n return \"\";\n var formattedValue = value.toString();\n if (currencyCode) {\n var convertedValue = kbService.fxConvert(value, currencyCode.toUpperCase());\n formattedValue = $filter(\"kbCurrency\")(convertedValue, currencyCode.toUpperCase(), precision);\n }\n return formattedValue;\n });\n }\n FxConvertFilter = __decorate([\n NgFilter({\n token: Token.FxConvertFilter,\n dependencies: [\n Token.$Filter,\n Token.KbService,\n ]\n })\n ], FxConvertFilter);\n return FxConvertFilter;\n }());\n\n var GetFileExtensionFilter = /** @class */ (function () {\n function GetFileExtensionFilter() {\n return (function (path) {\n var filename = path.substring(path.lastIndexOf(\"/\") + 1);\n return filename.substring(path.lastIndexOf(\".\") + 1);\n });\n }\n GetFileExtensionFilter = __decorate([\n NgFilter({\n token: Token.GetFileExtensionFilter,\n dependencies: []\n })\n ], GetFileExtensionFilter);\n return GetFileExtensionFilter;\n }());\n\n var GetFilenameFilter = /** @class */ (function () {\n function GetFilenameFilter() {\n return (function (path) {\n var filename = path.substring(path.lastIndexOf(\"/\") + 1);\n return filename;\n });\n }\n GetFilenameFilter = __decorate([\n NgFilter({\n token: Token.GetFilenameFilter,\n dependencies: []\n })\n ], GetFilenameFilter);\n return GetFilenameFilter;\n }());\n\n var HasRoleFilter = /** @class */ (function () {\n function HasRoleFilter(authService) {\n var _this = this;\n this.authService = authService;\n return (function (role) {\n return _this.authService.hasRole(role);\n });\n }\n HasRoleFilter = __decorate([\n NgFilter({\n token: Token.HasRoleFilter,\n dependencies: [\n Token.AuthService\n ]\n })\n ], HasRoleFilter);\n return HasRoleFilter;\n }());\n\n var IconFilter = /** @class */ (function () {\n function IconFilter() {\n return (function (key) {\n if (key)\n key = key.toCamelCase();\n var icon = _tools.icons[key];\n if (!icon) {\n icon = key;\n }\n return icon;\n });\n }\n IconFilter = __decorate([\n NgFilter({\n token: Token.IconFilter,\n dependencies: []\n })\n ], IconFilter);\n return IconFilter;\n }());\n\n var IsAdminOrCompanyAdminFilter = /** @class */ (function () {\n function IsAdminOrCompanyAdminFilter(authService) {\n var _this = this;\n this.authService = authService;\n return (function (user) {\n return _this.authService.isAdminOrCompanyAdmin();\n });\n }\n IsAdminOrCompanyAdminFilter = __decorate([\n NgFilter({\n token: Token.IsAdminOrCompanyAdminFilter,\n dependencies: [\n Token.AuthService\n ]\n })\n ], IsAdminOrCompanyAdminFilter);\n return IsAdminOrCompanyAdminFilter;\n }());\n\n // declare module \"angular\" {\n // interface IFilterService {\n // (name: \"kbCurrency\"): IKbCurrencyFilter;\n // }\n // }\n var KbCurrencyFilter = /** @class */ (function () {\n function KbCurrencyFilter($filter, $rootScope, $locale) {\n return (function (value, currencyCode, precision) {\n // if no iso given, then assume it's the company base currency\n // in future, should be the currency of the active quote\n if (!currencyCode) {\n // if ($rootScope.quote) {\n // currencyCode = $rootScope.quote.currency;\n // }\n // else {\n currencyCode = $rootScope.companySettings.currency;\n // }\n }\n currencyCode = currencyCode.toUpperCase();\n var symbol = _tools.currencies[currencyCode] || \"\";\n var formatted = $filter(\"currency\")(Number(value), undefined, precision);\n var localSymbol = $locale.NUMBER_FORMATS.CURRENCY_SYM;\n // replace local symbol in formatted with the real symbol\n formatted = formatted.replace(localSymbol, symbol);\n // add the iso code at the end\n formatted = formatted + \" \" + currencyCode;\n return formatted;\n });\n }\n KbCurrencyFilter = __decorate([\n NgFilter({\n token: Token.KbCurrencyFilter,\n dependencies: [\n Token.$Filter,\n Token.$RootScope,\n Token.$Locale,\n ]\n })\n ], KbCurrencyFilter);\n return KbCurrencyFilter;\n }());\n\n var KbDateTimeFilter = /** @class */ (function () {\n function KbDateTimeFilter() {\n return (function (d) {\n return d.getFullYear().toString() + \"/\" +\n (d.getMonth() + 1).toString() + \"/\" +\n d.getDate().toString() + \" \" +\n d.getHours() + \":\" +\n d.getMinutes();\n });\n }\n KbDateTimeFilter = __decorate([\n NgFilter({\n token: Token.KbDateTimeFilter,\n dependencies: []\n })\n ], KbDateTimeFilter);\n return KbDateTimeFilter;\n }());\n\n var KbDateFilter = /** @class */ (function () {\n function KbDateFilter() {\n return (function (d) {\n return d.getFullYear().toString() + \"/\" + (d.getMonth() + 1).toString() + \"/\" + d.getDate().toString();\n });\n }\n KbDateFilter = __decorate([\n NgFilter({\n token: Token.KbDateFilter,\n dependencies: []\n })\n ], KbDateFilter);\n return KbDateFilter;\n }());\n\n /**\n * converts a number of days to a human readable format: like '10 days', '7.5 weeks', '3 months'\n */\n var LeadTimeFilter = /** @class */ (function () {\n function LeadTimeFilter() {\n return (function (days, singular) {\n if (singular === void 0) { singular = false; }\n if (days < 14) {\n return days + \" \" + (singular ? loc.day : loc.days);\n }\n else if (days < 90) {\n return (days / 7).rounder(1).toString() + \" \" + (singular ? loc.week : loc.weeks);\n }\n else {\n return (days / 30.42).rounder(1).toString() + \" \" + (singular ? loc.month : loc.months);\n }\n });\n }\n LeadTimeFilter = __decorate([\n NgFilter({\n token: Token.LeadTimeFilter,\n dependencies: []\n })\n ], LeadTimeFilter);\n return LeadTimeFilter;\n }());\n\n var LocFilter = /** @class */ (function () {\n function LocFilter() {\n return (function (key) {\n var replacements = [];\n for (var _i = 1; _i < arguments.length; _i++) {\n replacements[_i - 1] = arguments[_i];\n }\n if (key) {\n // replacements = [replacement1, replacement2];\n var lkey = key.toLowerCase();\n var localizedString = loc[lkey];\n if (localizedString) {\n var result = localizedString.format.apply(localizedString, replacements);\n return result;\n }\n }\n return key;\n });\n }\n LocFilter = __decorate([\n NgFilter({\n token: Token.LocFilter,\n dependencies: []\n })\n ], LocFilter);\n return LocFilter;\n }());\n\n var LogIconFilter = /** @class */ (function () {\n function LogIconFilter() {\n return (function (type) {\n switch (type) {\n case enums.eLogType.error:\n return _tools.icons.error;\n case enums.eLogType.info:\n return _tools.icons.info;\n default:\n return _tools.icons.success;\n }\n });\n }\n LogIconFilter = __decorate([\n NgFilter({\n token: Token.LogIconFilter,\n dependencies: []\n })\n ], LogIconFilter);\n return LogIconFilter;\n }());\n\n // declare module \"angular\" {\n // interface IFilterService {\n // (name: \"media\"): IMediaFilter;\n // }\n // }\n var MediaFilter = /** @class */ (function () {\n function MediaFilter(storageService) {\n return (function (mediaPath) {\n if (!mediaPath) {\n return storageService.getFallbackImage();\n }\n else {\n return storageService.getMediaUrl(mediaPath);\n }\n });\n }\n MediaFilter = __decorate([\n NgFilter({\n token: Token.MediaFilter,\n dependencies: [\n Token.StorageService\n ]\n })\n ], MediaFilter);\n return MediaFilter;\n }());\n\n var NotificationIconFilter = /** @class */ (function () {\n function NotificationIconFilter() {\n return (function (type) {\n switch (type) {\n case enums.eNotificationType.quoteApproved:\n return _tools.icons.approve;\n case enums.eNotificationType.quoteRejected:\n return _tools.icons.reject;\n default:\n return _tools.icons.user;\n }\n });\n }\n NotificationIconFilter = __decorate([\n NgFilter({\n token: Token.NotificationIconFilter,\n dependencies: []\n })\n ], NotificationIconFilter);\n return NotificationIconFilter;\n }());\n\n var NumberFormatFilter = /** @class */ (function () {\n function NumberFormatFilter() {\n return (function (value, format, minPrecision, maxPrecision, currency, decimalSeparator, thousandsSeparator, prefix, suffix) {\n return value.format({\n formatType: format,\n minPrecision: Number(minPrecision),\n maxPrecision: Number(maxPrecision),\n currency: currency,\n decimalSeparator: decimalSeparator,\n thousandsSeparator: thousandsSeparator,\n prefix: prefix,\n suffix: suffix\n });\n });\n }\n NumberFormatFilter = __decorate([\n NgFilter({\n token: Token.NumberFormateFilter,\n dependencies: []\n })\n ], NumberFormatFilter);\n return NumberFormatFilter;\n }());\n\n var ProfileImageFilter = /** @class */ (function () {\n function ProfileImageFilter(storageService) {\n return (function (path) {\n if (!path) {\n return storageService.getFallbackImage();\n }\n else {\n return storageService.getProfileImageUrl(path);\n }\n });\n }\n ProfileImageFilter = __decorate([\n NgFilter({\n token: Token.ProfileImageFilter,\n dependencies: [\n Token.StorageService\n ]\n })\n ], ProfileImageFilter);\n return ProfileImageFilter;\n }());\n\n var QuoteProductImageFilter = /** @class */ (function () {\n function QuoteProductImageFilter(storageService) {\n return (function (relativePath) {\n if (!relativePath) {\n return storageService.getFallbackImage();\n }\n else if (relativePath.startsWith(\"media/\") || relativePath.startsWith(\"productimages/\")) {\n // if it's a media file, go straight to the blob storage to spare the round trip and redirect\n return storageService.getFileUrl(relativePath);\n }\n else {\n return \"/api/\" + relativePath;\n }\n });\n }\n QuoteProductImageFilter = __decorate([\n NgFilter({\n token: Token.QuoteProductImageFilter,\n dependencies: [\n Token.StorageService\n ]\n })\n ], QuoteProductImageFilter);\n return QuoteProductImageFilter;\n }());\n\n /**\n * used in ng-repeat to have something like a for loop instead of looping over a collection\n */\n var RangeFilter = /** @class */ (function () {\n function RangeFilter() {\n return (function (input, total) {\n total = parseInt(total, 10);\n for (var i = 0; i < total; i++) {\n input.push(i);\n }\n return input;\n });\n }\n RangeFilter = __decorate([\n NgFilter({\n token: Token.RangeFilter,\n dependencies: []\n })\n ], RangeFilter);\n return RangeFilter;\n }());\n\n /**\n * convert html to raw text\n */\n var RawTextFilter = /** @class */ (function () {\n function RawTextFilter() {\n return (function (html) {\n return String(html).replace(/<(?:.|\\n)*?>/gm, \"\");\n });\n }\n RawTextFilter = __decorate([\n NgFilter({\n token: Token.RawTextFilter,\n dependencies: []\n })\n ], RawTextFilter);\n return RawTextFilter;\n }());\n\n var ShadeFilter = /** @class */ (function () {\n function ShadeFilter() {\n return (function (shadeEnumValue, colorName) {\n var shadeNum = 50;\n if (shadeEnumValue.startsWith(\"lighter\")) {\n shadeNum = Number(shadeEnumValue.substr(7)) * 10;\n }\n else if (shadeEnumValue.startsWith(\"darker\")) {\n shadeNum = (Number(shadeEnumValue.substr(6)) * 10) + 50;\n }\n var prefix = \"kb-background\";\n return \"\".concat(prefix, \"--\").concat(colorName.toLowerCase(), \"-\").concat(shadeNum);\n });\n }\n ShadeFilter = __decorate([\n NgFilter({\n token: Token.ShadeFilter,\n dependencies: []\n })\n ], ShadeFilter);\n return ShadeFilter;\n }());\n\n /**\n * Given a background color, will provide a contrasting foreground color as a hex code\n */\n var SmartColorFilter = /** @class */ (function () {\n function SmartColorFilter() {\n return (function (backgroundHex) {\n var color;\n var background = new _tools.Color(backgroundHex);\n if (background.isDark()) {\n color = new _tools.Color({ r: 250, g: 250, b: 250 });\n }\n else {\n color = new _tools.Color({ r: 17, g: 17, b: 17 });\n }\n return color.toHexString();\n });\n }\n SmartColorFilter = __decorate([\n NgFilter({\n token: Token.SmartColorFilter,\n dependencies: []\n })\n ], SmartColorFilter);\n return SmartColorFilter;\n }());\n\n var ThemeColorFilter = /** @class */ (function () {\n function ThemeColorFilter(themeService, $rootScope) {\n return (function (palette, shadeEnumValue, opacity, contrast) {\n var shadeNum = 50;\n if (shadeEnumValue.startsWith(\"lighter\")) {\n shadeNum = Number(shadeEnumValue.substr(7)) * 10;\n }\n else if (shadeEnumValue.startsWith(\"darker\")) {\n shadeNum = (Number(shadeEnumValue.substr(6)) * 10) + 50;\n }\n if (palette == \"warning\") {\n palette = \"warn\";\n }\n return themeService.getRgbString(themeService.getActiveTheme(), palette, shadeNum, opacity, contrast, false);\n });\n }\n ThemeColorFilter = __decorate([\n NgFilter({\n token: Token.ThemeColorFilter,\n dependencies: [\n Token.ThemeService,\n Token.$RootScope\n ]\n })\n ], ThemeColorFilter);\n return ThemeColorFilter;\n }());\n\n // declare module \"angular\" {\n // interface IFilterService {\n // (name: \"thumb\"): IThumbFilter;\n // }\n // }\n var ThumbFilter = /** @class */ (function () {\n function ThumbFilter(storageService) {\n return (function (mediaPath, width, height) {\n var path = mediaPath;\n if (mediaPath) {\n if (!_tools.Utils.isAbsoluteUrl(mediaPath)) {\n // if the consumer is asking for a size bigger than our thumbnails, then we load the full res image\n if ((width && width > 90) || (height && height > 90)) {\n path = storageService.getMediaUrl(mediaPath);\n }\n else { // size is thumbnail size or lower, so we load the thumbnail for speed\n path = \"\".concat(storageService.getMediaUrl(mediaPath), \"?width=96&height=96\");\n }\n }\n }\n return path;\n });\n }\n ThumbFilter = __decorate([\n NgFilter({\n token: Token.ThumbFilter,\n dependencies: [\n Token.StorageService\n ]\n })\n ], ThumbFilter);\n return ThumbFilter;\n }());\n\n var TruncateFilter = /** @class */ (function () {\n function TruncateFilter() {\n return (function (text, length, end) {\n if (isNaN(length)) {\n length = 10;\n }\n if (!angular.isDefined(end)) {\n end = \"...\";\n }\n if (!text || text.length - end.length <= length) {\n return text;\n }\n else {\n return String(text).substring(0, length - end.length) + end;\n }\n });\n }\n TruncateFilter = __decorate([\n NgFilter({\n token: Token.TruncateFilter,\n dependencies: []\n })\n ], TruncateFilter);\n return TruncateFilter;\n }());\n\n var TrustAsHtmlFilter = /** @class */ (function () {\n function TrustAsHtmlFilter($sce) {\n return (function (html) {\n return $sce.trustAsHtml(html);\n });\n }\n TrustAsHtmlFilter = __decorate([\n NgFilter({\n token: Token.TrustAsHtmlFilter,\n dependencies: [\n Token.$Sce\n ]\n })\n ], TrustAsHtmlFilter);\n return TrustAsHtmlFilter;\n }());\n\n (function (eClaraPropertyType) {\n eClaraPropertyType[\"string\"] = \"string\";\n eClaraPropertyType[\"number\"] = \"number\";\n eClaraPropertyType[\"boolean\"] = \"boolean\";\n eClaraPropertyType[\"color\"] = \"color\";\n eClaraPropertyType[\"reference\"] = \"reference\";\n })(exports.eClaraPropertyType || (exports.eClaraPropertyType = {}));\n (function (eHighlightType) {\n eHighlightType[\"user\"] = \"user\";\n eHighlightType[\"hover\"] = \"hover\";\n eHighlightType[\"selection\"] = \"selection\";\n })(exports.eHighlightType || (exports.eHighlightType = {}));\n var ClaraSceneUtilities = /** @class */ (function () {\n function ClaraSceneUtilities(sceneService, sceneApi, ruleType, idMap, nestedSceneId) {\n this.sceneService = sceneService;\n this.sceneApi = sceneApi;\n this.ruleType = ruleType;\n this.idMap = idMap;\n this.nestedSceneId = nestedSceneId;\n }\n ClaraSceneUtilities.prototype.setProperty = function (args) {\n args.nestedSceneId = this.nestedSceneId;\n args.objectId = this.mapId(args.objectId);\n args.value = this.mapId(args.value); // sometimes the value is an id as well (like setting a material reference)\n this.sceneService.setProperty(this.sceneApi, args);\n if (this.sceneApi.afterSetProperty)\n this.sceneApi.afterSetProperty(args);\n };\n ClaraSceneUtilities.prototype.getProperty = function (args) {\n args.nestedSceneId = this.nestedSceneId;\n args.objectId = this.mapId(args.objectId);\n return this.sceneService.getProperty(this.sceneApi, args);\n };\n ClaraSceneUtilities.prototype.setVisible = function (args) {\n args.nestedSceneId = this.nestedSceneId;\n args.objectId = this.mapId(args.objectId);\n return this.sceneService.setVisibleRecursively(this.sceneApi, args);\n };\n ClaraSceneUtilities.prototype.frameScene = function (args) {\n return this.sceneService.frameScene(this.sceneApi, args);\n };\n ClaraSceneUtilities.prototype.animateCamera = function (args) {\n return this.sceneService.animateCamera(this.sceneApi, args);\n };\n ClaraSceneUtilities.prototype.animate = function (args) {\n args.objectId = this.mapId(args.objectId);\n this.sceneService.animate(this.sceneApi, args);\n if (this.sceneApi.afterAnimateProperty)\n this.sceneApi.afterAnimateProperty(args);\n };\n ClaraSceneUtilities.prototype.animateClip = function (args) {\n return this.sceneService.animateClip(this.sceneApi, args);\n };\n ClaraSceneUtilities.prototype.addModelClickHandler = function (args) {\n args.modelId = this.mapId(args.modelId);\n args.addedByRuleType = this.ruleType;\n // we need a unique id for the handler, but in the context of the nested configurator.\n if (this.nestedSceneId) {\n args.uniqueId = this.nestedSceneId + \"-\" + args.uniqueId;\n if (args.hotspotId) {\n args.hotspotId = this.nestedSceneId + \"-\" + args.hotspotId;\n }\n }\n if (this.sceneApi.addModelClickHandler) {\n return this.sceneApi.addModelClickHandler(args);\n }\n };\n ClaraSceneUtilities.prototype.clearClickHandlers = function () {\n if (this.sceneApi.clickDb)\n this.sceneApi.clearClickHandlers();\n };\n ClaraSceneUtilities.prototype.addDraggable = function (args) {\n args.addedByRuleType = this.ruleType;\n args.objectId = this.mapId(args.objectId);\n this.sceneApi.addDraggable(args);\n };\n ClaraSceneUtilities.prototype.clearDraggables = function () {\n if (this.sceneApi.draggableDb)\n this.sceneApi.clearDraggables();\n };\n ClaraSceneUtilities.prototype.ghost = function (args) {\n return this.sceneService.ghost(this.sceneApi, args);\n };\n ClaraSceneUtilities.prototype.clearGhosts = function () {\n return this.sceneService.clearGhosts(this.sceneApi);\n };\n ClaraSceneUtilities.prototype.highlight = function (args) {\n return this.sceneService.highlight(this.sceneApi, args, exports.eHighlightType.user);\n };\n ClaraSceneUtilities.prototype.clearHighlights = function () {\n return this.sceneService.clearHighlightsOfType(this.sceneApi, exports.eHighlightType.user);\n };\n ClaraSceneUtilities.prototype.select = function (args) {\n return this.sceneService.select(this.sceneApi, args);\n };\n ClaraSceneUtilities.prototype.clearSelection = function () {\n return this.sceneService.clearSelection(this.sceneApi);\n };\n ClaraSceneUtilities.prototype.getId = function (args) {\n return this.sceneApi.cache.paths.getId({ name: args.name });\n };\n ClaraSceneUtilities.prototype.getName = function (args) {\n return this.sceneApi.api.scene.get({ id: args.id, property: \"name\" });\n };\n ClaraSceneUtilities.prototype.mapId = function (id) {\n return this.idMap ? this.idMap[id] || id : id;\n };\n ClaraSceneUtilities.prototype.getNode = function (args) {\n var o = this.sceneService.getQueryObject(this.sceneApi, args.id, null);\n var id = this.sceneApi.cache.paths.getId(o);\n var name = this.sceneApi.api.scene.get({ id: id, property: \"name\" });\n var t = this.sceneApi.api.scene.get({ id: id, property: \"type\" });\n return {\n id: id,\n name: name,\n type: t\n };\n };\n ClaraSceneUtilities.prototype.getChildNodes = function (args) {\n var _this = this;\n var children = [];\n var o = this.sceneService.getQueryObject(this.sceneApi, args.id, null);\n var id = this.sceneApi.cache.paths.getId(o);\n if (id) {\n // TODO: 2018-01-19 (RH): Had to cast this to due to a type mismatch error in the\n // new TS 2.5 compiler.\n var childIds = this.sceneApi.api.scene.filter({ from: id });\n if (childIds && childIds.length) {\n childIds.forEach(function (childId) {\n children.push(_this.getNode({ id: childId }));\n });\n }\n }\n return children;\n };\n ClaraSceneUtilities.prototype.whenAssetsLoaded = function () {\n return this.sceneApi.api.sceneIO.whenLoaded();\n };\n ClaraSceneUtilities.prototype.getActiveCamera = function () {\n return this.sceneApi.api.player.getCamera();\n };\n return ClaraSceneUtilities;\n }());\n /**\n * PathCache stores a map between query objects and paths for the V2 player.\n * Paths are better because it doesn't result in a search.\n * We also store the last set value so we don't keep setting the current value\n * over and over which costs with performance.\n */\n var PathCache = /** @class */ (function () {\n function PathCache(sceneApi) {\n this.sceneApi = sceneApi;\n this._data = {};\n }\n PathCache.prototype.get = function (query) {\n var paths = this.getPaths(query, false);\n return paths.length ? paths.first() : [];\n };\n PathCache.prototype.getId = function (query) {\n var paths = this.getPaths(query, false);\n return paths.length ? paths.first() : null;\n };\n PathCache.prototype.getIds = function (query) {\n return this.getPaths(query, true);\n };\n PathCache.prototype.getAll = function (query) {\n return this.getPaths(query, true);\n };\n PathCache.prototype.clear = function () {\n this._data = {};\n };\n PathCache.prototype.clearEntriesThatContain = function () {\n var searchTerms = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n searchTerms[_i] = arguments[_i];\n }\n var keys = Object.keys(this._data);\n for (var _a = 0, keys_1 = keys; _a < keys_1.length; _a++) {\n var key = keys_1[_a];\n for (var _b = 0, searchTerms_1 = searchTerms; _b < searchTerms_1.length; _b++) {\n var term = searchTerms_1[_b];\n if (key.indexOf(term) > -1) {\n delete this._data[key];\n break;\n }\n }\n }\n };\n PathCache.prototype.getPaths = function (query, forSetAll) {\n var key = JSON.stringify(query);\n var exists = this._data.hasOwnProperty(key);\n if (exists) {\n return this._data[key];\n }\n else {\n var paths = [];\n if (forSetAll) {\n paths = this.sceneApi.api.scene.filter(query);\n }\n else {\n var path = this.sceneApi.api.scene.find(query);\n if (path)\n paths.push(path);\n }\n if (!paths.length) {\n console.warn(\"cannot find object with query: \" + JSON.stringify(query));\n }\n else {\n this._data[key] = paths;\n }\n return paths;\n }\n };\n return PathCache;\n }());\n var LastValueCache = /** @class */ (function () {\n function LastValueCache() {\n this._data = {};\n }\n LastValueCache.prototype.get = function (path) {\n var key = JSON.stringify(path);\n return this._data[key];\n };\n LastValueCache.prototype.set = function (path, value) {\n this._data[JSON.stringify(path)] = JSON.stringify(value);\n };\n LastValueCache.prototype.valueEqualTo = function (path, val) {\n var key = JSON.stringify(path);\n return this._data[key] === JSON.stringify(val);\n };\n return LastValueCache;\n }());\n var SceneCache = /** @class */ (function () {\n function SceneCache(sceneApi) {\n this.sceneApi = sceneApi;\n this.paths = new PathCache(this.sceneApi);\n this.lastValues = new LastValueCache();\n }\n return SceneCache;\n }());\n var ClaraSceneService = /** @class */ (function () {\n function ClaraSceneService(ruleService, $q) {\n this.ruleService = ruleService;\n this.$q = $q;\n this._vectorProperties = [\n \"translationx\",\n \"translationy\",\n \"translationz\",\n \"rotationx\",\n \"rotationy\",\n \"rotationz\",\n \"scalex\",\n \"scaley\",\n \"scalez\"\n ];\n this.NESTED_SCENE_PREFIX = \"kb-nested-\";\n }\n ClaraSceneService.prototype.convertColorForScene = function (hex) {\n // clara expects rgb values from 0 to 1\n var color = new _tools.Color(hex).toRgb();\n color.r = color.r / 255;\n color.g = color.g / 255;\n color.b = color.b / 255;\n return color;\n };\n ClaraSceneService.prototype.normalizePropertyValue = function (sceneApi, args) {\n var origValue = args.value;\n if (args.propertyType && args.propertyType.isEqual(\"Color\")) { // property type is the clara data type, not the snap data type\n // if value is already an rgb object, then skip this\n if (args.value &&\n typeof args.value === \"object\" &&\n args.value.hasOwnProperty(\"r\") &&\n args.value.hasOwnProperty(\"g\") &&\n args.value.hasOwnProperty(\"b\")) ;\n else if (args.value !== null) {\n args.value = this.convertColorForScene(args.value);\n }\n }\n if (this._vectorProperties.indexOf(args.property) > -1) {\n var axis = args.property.charAt(args.property.length - 1);\n args.property = args.property.substr(0, args.property.length - 1);\n var currentVal = this.getProperty(sceneApi, {\n objectId: args.objectId,\n name: args.name,\n plug: args.plug,\n operator: args.operator,\n property: args.property,\n propertyType: null,\n nestedSceneId: args.nestedSceneId\n });\n if (currentVal && currentVal.clone)\n currentVal = currentVal.clone();\n currentVal[axis] = origValue;\n args.value = currentVal;\n }\n };\n ClaraSceneService.prototype.toggleTool = function (sceneApi, args) {\n sceneApi.api.commands.updateCommand(args.tool, { enabled: args.enabled });\n };\n ClaraSceneService.prototype.constrainCamera = function (sceneApi, args) {\n var radius = args.constrain ? args.radius : null;\n sceneApi.api.player.setCameraRadiusConstraint(radius);\n };\n /**\n * validates that the given string is a valid clara id. Note that clara used to use guids,\n * and now uses these: https://github.com/ericelliott/cuid\n * so we need to validate for both\n * @param id\n */\n ClaraSceneService.prototype.isClaraId = function (id) {\n var cuidRegex = /^c[^\\s-]{8,}$/;\n return _tools.Utils.isGuid(id) || (cuidRegex.exec(id) != null);\n };\n ClaraSceneService.prototype.getParentNodeId = function (sceneApi, nodeId) {\n return sceneApi.api.scene.find({\n id: nodeId,\n parent: true\n });\n };\n ClaraSceneService.prototype.getChildNodeIds = function (sceneApi, nodeId) {\n return sceneApi.api.scene.filter({ from: nodeId });\n };\n ClaraSceneService.prototype.findAncestorNodeId = function (sceneApi, nodeId, callback) {\n var parentId = nodeId;\n while (parentId) {\n if (callback(parentId))\n break;\n parentId = this.getParentNodeId(sceneApi, parentId);\n }\n return parentId;\n };\n ClaraSceneService.prototype.getProperty = function (sceneApi, args) {\n var axis;\n if (this._vectorProperties.indexOf(args.property) > -1) {\n axis = args.property.charAt(args.property.length - 1);\n args.property = args.property.substr(0, args.property.length - 1);\n }\n var query = this.getQueryObjectFromArgs(sceneApi, args);\n // if the item is in a nested scene, we must look for the item only in the nested scene null,\n // otherwise regex style sets will be applied to the whole scene\n // materials are not nested under the nested scene null so they do not apply & \n // from is not needed if doing an id search, so we only use it when doing by name\n if (args.nestedSceneId && query.name && !args.operator.equalsAny(\"Physical\", \"Canvas\", \"CanvasText\")) {\n query.from = { id: args.nestedSceneId };\n }\n var path = sceneApi.cache.paths.get(query);\n var result = null;\n result = sceneApi.api.scene.get(path);\n if (axis && result) {\n result = result[axis];\n }\n return result;\n };\n ClaraSceneService.prototype.setProperty = function (sceneApi, args) {\n this.normalizePropertyValue(sceneApi, args);\n // if this is a reference type, then we need to set the reference property to the id of the referenced item\n if (args.propertyType && args.propertyType.isEqual(\"Node\")) { // property type is the clara data type, not the snap data type\n if (!this.isClaraId(args.value)) {\n args.value = sceneApi.cache.paths.getId({ name: args.value });\n }\n }\n var query = this.getQueryObjectFromArgs(sceneApi, args);\n // if the item is in a nested scene, we must look for the item only in the nested scene null,\n // otherwise regex style sets will be applied to the whole scene\n // materials are not nested under the nested scene null so they do not apply & \n // from is not needed if doing an id search, so we only use it when doing by name\n if (args.nestedSceneId && query.name && !args.operator.equalsAny(\"Physical\", \"Canvas\", \"CanvasText\")) {\n query.from = { id: args.nestedSceneId };\n }\n var setAll = (query.name != null); // we use setAll if this is possibly a regex query\n var paths = sceneApi.cache.paths.getAll(query);\n paths.forEach(function (path) {\n if (!sceneApi.cache.lastValues.valueEqualTo(path, args.value)) {\n sceneApi.api.scene.set(path, args.value);\n _tools.Logger.logSceneChange(\"set \" + JSON.stringify(args));\n sceneApi.cache.lastValues.set(path, args.value);\n }\n });\n };\n ClaraSceneService.prototype.setVisibleRecursively = function (sceneApi, args) {\n // hierarchical visibility is not set, so we fallback to what we used to do, which is setting the node and all it's children's visibility to simulate hierarchical visibility\n var query = { name: \"*\", plug: \"Properties\", property: \"visible\" };\n query.includeParent = true; // include the parent in the query\n query.from = this.getQueryObject(sceneApi, args.objectId, args.name);\n if (!query.from)\n return;\n // if we're in a nested scene, then only look for nodes inside of that\n if (args.nestedSceneId) {\n query.from.from = { id: args.nestedSceneId };\n }\n var paths = sceneApi.cache.paths.getAll(query);\n if (paths) {\n paths.forEach(function (path) {\n if (!sceneApi.cache.lastValues.valueEqualTo(path, args.visible)) {\n sceneApi.api.scene.set(path, args.visible);\n _tools.Logger.logSceneChange(\"set \" + JSON.stringify(args));\n sceneApi.cache.lastValues.set(path, args.visible);\n }\n });\n }\n };\n ClaraSceneService.prototype.getQueryObjectFromArgs = function (sceneApi, args) {\n return this.getQueryObject(sceneApi, args.objectId, args.name, args.plug, args.property, args.operator);\n };\n ClaraSceneService.prototype.getQueryObject = function (sceneApi, id, name, plug, property, operator) {\n var o = {};\n // temporary check for transition to V2. Old blocks will only be using objectId even if it's the name \n // we're after newer blocks differentiate. So we need to make sure the id is really an id. \n // If it isn't, then we'll use it as the name\n if (id) {\n var foundId = sceneApi.api.scene.find({ id: id });\n if (foundId) {\n o.id = id;\n }\n else {\n o.name = id;\n }\n }\n else if (name) {\n o.name = name;\n }\n if (plug) {\n o.plug = plug;\n }\n if (property) {\n o.property = property;\n }\n if (operator) {\n // using named operators is a little strange. We need to match the operator through it's properties. \n // In this case, we use the name property\n o.properties = { name: operator };\n }\n return o;\n };\n ClaraSceneService.prototype.animateCamera = function (sceneApi, args) {\n var duration = args.duration || 3000;\n var easing = args.easing || \"linear\";\n sceneApi.cameraAnimationInProgress = true;\n return sceneApi.api.player.animateCameraTo(args.toCameraId, duration).then(function () {\n sceneApi.cameraAnimationInProgress = false;\n });\n };\n ClaraSceneService.prototype.animate = function (sceneApi, args) {\n this.normalizePropertyValue(sceneApi, args);\n var query = this.getQueryObjectFromArgs(sceneApi, args);\n var setAll = (query.name != null); // we use setAll if this is possibly a regex query\n var paths = sceneApi.cache.paths.getAll(query);\n paths.forEach(function (path) {\n // if (!sceneApi.cache.lastValues.valueEqualTo(path, args.value)) {\n sceneApi.api.animation.queueAnimation({\n name: _tools.Utils.shortId(),\n iterations: args.iterations,\n autoplay: true,\n tracks: [\n {\n path: path,\n type: args.propertyType,\n value: args.value,\n duration: args.duration,\n easing: args.easing || \"linear\",\n start: args.start\n }\n ],\n onEnd: function () {\n // after the animation set the value in the cache\n sceneApi.cache.lastValues.set(path, args.value);\n }\n });\n // }\n });\n };\n ClaraSceneService.prototype.animateClip = function (sceneApi, args) {\n var clip = sceneApi.api.animation.getClips().find(function (c) { return c.name.isEqual(args.name); });\n if (clip) {\n sceneApi.api.animation.queueClip(clip.id, { autoplay: true });\n }\n else {\n console.warn(\"Could not find animation clip with name '\" + args.name + \"'\");\n }\n };\n ClaraSceneService.prototype.getSceneUtilities = function (sceneApi, ruleType, idMap, nestedSceneId) {\n return new ClaraSceneUtilities(this, sceneApi, ruleType, idMap, nestedSceneId);\n };\n ClaraSceneService.prototype.runSceneRules = function (sceneConfig, uiConfig, ruleArgs, skipRulesIfNoNestedSceneChanges) {\n var _this = this;\n return this.runNestedSceneRules(ruleArgs.sceneApi, uiConfig).then(function (r) {\n if (!skipRulesIfNoNestedSceneChanges || (r && r.some(function (r2) { return r2 != null; }))) { //skip running the rules if there were no nested scene rules run\n return _this.importAllUploadFieldImages(ruleArgs.sceneApi, uiConfig).then(function () {\n ruleArgs.sceneUtils.ruleType = enums.eRuleType.scene;\n return _this.ruleService.runRuleTypeAsync(sceneConfig, enums.eRuleType.scene, ruleArgs).then(function (ruleResult) {\n uiConfig.$fieldsDirtyForSceneRules = false;\n return ruleResult;\n });\n });\n }\n });\n };\n ClaraSceneService.prototype.runRulesCycle = function (sceneConfig, uiConfig, ruleArgs) {\n var _this = this;\n var runUiRules = !ruleArgs.sceneApi.sceneDb[sceneConfig.idScene].idProduct;\n // before running the scene rules, we need to clear out transient handlers\n ruleArgs.sceneApi.draggableDb.clearTransient();\n ruleArgs.sceneApi.clickDb.clearTransient();\n if (runUiRules) {\n // run the value rule first\n ruleArgs.sceneUtils.ruleType = enums.eRuleType.value;\n return this.ruleService.runRuleTypeAsync(sceneConfig, enums.eRuleType.value, ruleArgs)\n .then(function () {\n sceneConfig.preValidate();\n sceneConfig.isValid();\n })\n .then(function () { return _this.runSceneRules(sceneConfig, uiConfig, ruleArgs, false); });\n }\n else {\n return this.runSceneRules(sceneConfig, uiConfig, ruleArgs, false);\n }\n };\n ClaraSceneService.prototype.runNestedSceneRules = function (sceneApi, uiConfig) {\n var _this = this;\n var nestedConfigs = uiConfig.getNestedConfigurators();\n if (nestedConfigs.length) {\n var promises_1 = [];\n // loop through nested configurators, merge the scenes if they haven't been already, and run their rules\n nestedConfigs.forEach(function (nested) {\n if (nested.idScene) {\n var refConfig = uiConfig.referencedConfigurators.find(function (rc) { return rc.idProduct == nested.idProduct; });\n if (refConfig.nestScene) {\n // create the scene configurator for the nested configurator if it doesn't already exist \n // (or has been swapped for another scene)\n if (!nested.$sceneConfigurator || nested.$sceneConfigurator.idScene != nested.idScene) {\n nested.$sceneConfigurator = new enums.Configurator(new enums.KbObjectManager(), sceneApi.sceneDb[nested.idScene].configurator);\n nested.$fieldsDirtyForSceneRules = true;\n }\n nested.$sceneConfigurator.$uiConfigurator = nested;\n nested.$nestHotspots = refConfig.nestHotspots;\n // in case the nested scene is a standalone scene, we need to set it's fields from the uiConfig\n if (nested != nested.$sceneConfigurator && !nested.$sceneConfigurator.idProduct) {\n nested.$sceneConfigurator.setFields(nested.getFieldsObject());\n }\n var skipRules_1 = !nested.$fieldsDirtyForSceneRules;\n promises_1.push(_this.nestScene(// merge the scene if it hasn't already been merged\n sceneApi, sceneApi.sceneDb[nested.idScene].claraId, sceneApi.sceneDb[nested.idScene].publishHash, nested).then(function () {\n // now run the rules on the nested scene\n return _this.runSceneRules(nested.$sceneConfigurator, nested, _this.getNestedSceneRuleArgs(sceneApi, nested, nested.$sceneConfigurator, nested.$sceneConfigurator.$sceneIdMap, enums.eRuleType.scene), skipRules_1);\n }));\n }\n }\n });\n return this.$q.all(promises_1);\n }\n else {\n return (new _rules.KPromise(null));\n }\n };\n ClaraSceneService.prototype.getNestedSceneRuleArgs = function (sceneApi, uiConfig, sceneConfig, idMap, ruleType) {\n // if the scene config is standalone, then it will also act as the uiConfig for the rules\n if (!sceneApi.sceneDb[uiConfig.idScene].idProduct)\n uiConfig = uiConfig.$sceneConfigurator;\n var sceneUtils = this.getSceneUtilities(sceneApi, ruleType, idMap, uiConfig.$nestedSceneId);\n return {\n environment: \"\",\n company: {},\n configurator: uiConfig,\n kom: uiConfig.$manager,\n parentKom: uiConfig.$parentConfigurator ? uiConfig.$parentConfigurator.$manager : null,\n sceneKom: sceneConfig.$manager,\n sceneApi: sceneApi,\n isRender: sceneApi.isRender,\n isMobile: sceneApi.isMobile,\n clientLanguage: sceneApi.clientLanguage,\n logs: new _rules.ClientLogger(),\n upload: function () {\n return new _rules.KPromise(null);\n },\n // TODO: leave in scene rule args for backwards compatibility. \n // Can be removed in the future, since it's real place is in scene utilities\n addModelClickHandler: function (args) {\n sceneUtils.addModelClickHandler(args);\n },\n playSceneAnimation: function (args) {\n // no need for animations server side\n },\n toggleSceneAnimation: function () {\n // no need for animations server side\n },\n sceneUtils: sceneUtils,\n sendMessage: function (msg) {\n sceneApi.sendMessage(msg);\n },\n selectPage: function (page) {\n },\n convertCurrency: function (obj) {\n return null;\n },\n toggleTool: function (args) {\n },\n constrainCamera: function (args) {\n },\n getUploadImageNode: function (args) {\n var a = sceneApi.importedImages[uiConfig.name + \"_\" + args.fieldId];\n return a ? a.imageNodeId : null;\n },\n getTables: function (args) {\n return sceneApi.getTables(args);\n }\n };\n };\n ClaraSceneService.prototype.nodeWithIdExists = function (sceneApi, id) {\n return id && (sceneApi.api.scene.find({ id: id }) != null);\n };\n ClaraSceneService.prototype.nestSceneInner = function () {\n };\n ClaraSceneService.prototype.fetchScene = function (sceneApi, claraId, publishHash) {\n if (!sceneApi.fetchedScenes.hasOwnProperty(claraId)) {\n sceneApi.fetchedScenes[claraId] =\n sceneApi.api.sceneIO.fetch(claraId, publishHash, { waitForPublish: true });\n }\n return sceneApi.fetchedScenes[claraId];\n };\n ClaraSceneService.prototype.nestScene = function (sceneApi, claraId, publishHash, nested) {\n var _this = this;\n // first check to see if this nested configurator scene has already been merged\n if (nested.$nestedSceneId && this.nodeWithIdExists(sceneApi, nested.$nestedSceneId)) {\n return (new _rules.KPromise(null));\n }\n else {\n var deferred_1 = this.$q.defer();\n var api_1 = sceneApi.api;\n var rootSceneId_1 = api_1.scene.find({ includeParent: true });\n // first fetch the scene from the server (or cache)\n this.fetchScene(sceneApi, claraId, publishHash).then(function () {\n // if this nested scene is a child of another nested scene, \n // then we must place this node inside of the parent nested scene node\n // otherwise, just put it in the 'Objects' node of the scene\n var parentId;\n if (nested.$parentConfigurator && nested.$parentConfigurator.$nestedSceneId) {\n parentId = nested.$parentConfigurator.$nestedSceneId;\n }\n else {\n parentId = sceneApi.cache.paths.getId({ type: \"Objects\" }); // get the 'Objects' node id\n }\n // now that we've fetched the nested scene template, we need to add a null node to house it\n api_1.sceneGraph.addNode({\n name: _this.NESTED_SCENE_PREFIX + nested.name,\n parent: parentId,\n type: \"Null\",\n plugs: {\n Transform: [[\"Transform\", {}]],\n Properties: [[\"Default\", {}]]\n }\n }).then(function (nullId) {\n // we have our new null node to house the nested scene. \n // Now we need to copy nodes from the other scene into it\n var nestedObjectsNodeId = sceneApi.cache.paths.getId({\n from: { id: claraId },\n name: \"Objects\"\n });\n var nestedMaterialsNodeId = sceneApi.cache.paths.getId({\n from: { id: claraId },\n name: \"Material Library\"\n });\n var parentMaterialsNodeId = sceneApi.cache.paths.getId({\n from: { id: rootSceneId_1 },\n name: \"Material Library\"\n });\n // only clone nodes that make sense - materials can stay where they're \n // at and still be used.Ignore cameras, lights, etc.\n var objectsToClone = api_1.scene.filter({\n from: { id: nestedObjectsNodeId },\n type: [\"PolyMesh\", \"BinMesh\", \"Null\", \"Model\", \"Annotation\", \"Helper\"]\n });\n var materialsToClone = api_1.scene.filter({\n from: { id: nestedMaterialsNodeId },\n type: [\"Material\"]\n });\n var allNodesToClone = objectsToClone.concat(materialsToClone);\n // create a parent map to tell the cloned nodes where to go\n var parentMap = {};\n // nested object nodes to go into our new null\n parentMap[nestedObjectsNodeId] = nullId;\n // nested material nodes to go into the parent material library\n parentMap[nestedMaterialsNodeId] = parentMaterialsNodeId;\n // this.dumpScene(sceneApi, api.scene.find({ includeParent: true }), 0);\n api_1.sceneGraph.clone(allNodesToClone, parentMap, { cloneDependencies: true }).then(function (nodeMap) {\n // console.log('new nodes', nodeMap);\n var sceneId = api_1.scene.find({ includeParent: true });\n // this.dumpScene(sceneApi, sceneId, 0);\n // this.checkScene(sceneApi, sceneId, 0, sceneId);\n // store the node map into the scene configurator\n nested.$sceneConfigurator.$sceneIdMap = nodeMap;\n // set the nested scene id of the configurator to make it easier to find this node by id\n nested.$nestedSceneId = nullId;\n if (sceneApi.onSceneNested) {\n sceneApi.onSceneNested(nested, nullId);\n }\n var nestedRuleArgs = _this.getNestedSceneRuleArgs(sceneApi, nested, nested.$sceneConfigurator, nested.$sceneConfigurator.$sceneIdMap, enums.eRuleType.sceneLoaded);\n _this.ruleService.runRuleTypeAsync(nested.$sceneConfigurator, enums.eRuleType.sceneLoaded, nestedRuleArgs).then(function () {\n deferred_1.resolve();\n });\n });\n });\n });\n return deferred_1.promise;\n }\n };\n ClaraSceneService.prototype.deleteOrphanedNestedScenes = function (sceneApi, uiConfig) {\n var allNested = uiConfig.getAllConfigurators();\n var api = sceneApi.api;\n var nestedSceneIds = api.scene.filter({ name: this.NESTED_SCENE_PREFIX + \"*\" });\n nestedSceneIds.forEach(function (id) {\n if (!allNested.some(function (c) { return c.$nestedSceneId == id; })) {\n api.sceneGraph.deleteNode(id);\n }\n });\n };\n /**\n * used to output the heirarchy for debugging\n * @param level\n */\n ClaraSceneService.prototype.dumpScene = function (sceneApi, nodeId, level) {\n var _this = this;\n var api = sceneApi.api;\n if (nodeId == null) {\n nodeId = sceneApi.api.scene.find({ includeParent: true });\n level = 0;\n }\n // tslint:disable-next-line:no-console\n console.log(new Array(level + 1).join(\" \"), \" - \", api.scene.get({ id: nodeId, property: \"name\" }), \" - \", nodeId);\n var paths = api.scene.filter({ from: { id: nodeId }, shallow: true });\n paths.forEach(function (id) { return _this.dumpScene(sceneApi, id, level + 1); });\n };\n ClaraSceneService.prototype.checkScene = function (sceneApi, nodeId, level, parentId) {\n var _this = this;\n var api = sceneApi.api;\n var name = api.scene.get({ id: nodeId, property: \"name\" });\n if (!name) {\n console.error(\"No data for child: \", nodeId, \"child of: \", api.scene.get({ id: parentId, property: \"name\" }));\n }\n var children = api._store.getIn([\"sceneGraph\", nodeId, \"children\"]);\n children.forEach(function (id) { return _this.checkScene(sceneApi, id, level + 1, nodeId); });\n };\n ClaraSceneService.prototype.importAllUploadFieldImages = function (sceneApi, uiConfig) {\n var _this = this;\n var promise = new _rules.KPromise(null);\n // only find fields with an assetId but don't have an image node yet. \n // The asset should have already been imported at time of upload\n // (has to be this way because we don't have the File object)\n var uploadFields = uiConfig.getFields(function (f) {\n return f.type == enums.eFieldType.upload &&\n f.uploadToScene;\n });\n if (uploadFields.length) {\n var promises_2 = [];\n uploadFields.forEach(function (uf) {\n promises_2.push(_this.importUploadFieldImage(sceneApi, uiConfig, uf));\n });\n promise = this.$q.all(promises_2);\n }\n return promise;\n };\n ClaraSceneService.prototype.importUploadFieldImage = function (sceneApi, uiConfig, field, file) {\n var promise = new _rules.KPromise(null);\n var uploadValue = field.value;\n var api = sceneApi.api;\n var isRender = sceneApi.isRender;\n // only import if the upload field is set to upload to scene\n if (field.uploadToScene) {\n var prefix = uiConfig.isNested() ? uiConfig.name : \"\";\n prefix += \"_\" + field.name;\n var nullNodeName_1 = prefix + \"_null\";\n var imageNodeName = prefix + \"_image\";\n var shapeNodeName_1 = prefix + \"_shape\";\n var extrudeNodeName_1 = prefix + \"_extrude\";\n var options = { outputName: imageNodeName };\n if (field.convertUploadedSceneImageToMesh) {\n options = {\n targetFormat: \"svg\",\n mode: \"threshold\",\n threshold: field.uploadImageThreshold,\n backgroundColor: \"#00FFFFFF\",\n outputName: imageNodeName\n };\n }\n // if there is already an asset id, and it has an image node, then there is nothing to do here\n // if there is no asset id, then this file still needs to get uploaded to assets\n var importObject = null;\n var prevImportedImage = sceneApi.importedImages[uiConfig.name + \"_\" + field.id];\n if (file && !uploadValue.assetId) { //user just uploaded \n importObject = file;\n }\n else if (uploadValue.assetId && !prevImportedImage) { //uploaded this session (and not an svg conversion)\n // pass the assetId to import to make the image node\n importObject = uploadValue.assetId;\n }\n if (importObject) {\n promise = sceneApi.api.assets.importImage(importObject, options);\n }\n else {\n return promise;\n }\n //clean up old svg image if it exists\n var svgNodeId = api.scene.find(imageNodeName + \".svg\");\n if (svgNodeId) {\n api.sceneGraph.deleteNode(svgNodeId);\n }\n promise.then(function (r) {\n uploadValue.assetId = r.assetId;\n sceneApi.importedImages[uiConfig.name + \"_\" + field.id] = { imageNodeId: r.imageNodeId, threshold: field.uploadImageThreshold };\n if (field.convertUploadedSceneImageToMesh) {\n //create a null to house the shape if one doesn't already exist\n var nullNodeId = api.scene.find(nullNodeName_1);\n if (!nullNodeId) {\n api.scene.addNode({\n name: nullNodeName_1,\n parent: api.scene.find('Objects'),\n type: \"Null\",\n plugs: {\n Transform: [[\"Transform\", {}]],\n Properties: [[\"Default\", {}]]\n }\n });\n nullNodeId = api.scene.find(nullNodeName_1);\n }\n //if the shape node already exists, then delete it\n //if it doesn't exist, then create it\n var shapeNodeId = api.scene.find(shapeNodeName_1);\n if (shapeNodeId) {\n api.sceneGraph.deleteNode(shapeNodeId);\n sceneApi.cache.paths.clearEntriesThatContain(shapeNodeName_1, shapeNodeId);\n }\n api.scene.addNode({\n name: shapeNodeName_1,\n type: 'Shape',\n parent: nullNodeId,\n plugs: {\n Shape: [\n [\n 'SVGShape',\n {\n image: r.imageNodeId,\n curveSegments: 8,\n },\n ],\n ]\n },\n });\n shapeNodeId = api.scene.find(shapeNodeName_1);\n // Resize shape (default operation is to fit a 1x1 square)\n api.scene.addOperator(shapeNodeId, 'Shape', 'ResizeShape', { keepAspectRatio: true });\n // Center the shape since center of svg is on top left corner\n api.scene.addOperator(shapeNodeId, 'Shape', 'CenterShape', {});\n //add an extrude of the shape\n var extrudeNodeId = api.scene.find(extrudeNodeName_1);\n if (extrudeNodeId) {\n api.sceneGraph.deleteNode(extrudeNodeId);\n sceneApi.cache.paths.clearEntriesThatContain(extrudeNodeName_1, extrudeNodeId);\n }\n api.scene.addNode({\n name: extrudeNodeName_1,\n type: \"PolyMesh\",\n parent: nullNodeId,\n plugs: {\n PolyMesh: [\n [\n \"FromShapeWithExtrude\",\n {\n shape: shapeNodeId,\n extrudeLength: 0.1\n }\n ]\n ]\n }\n });\n }\n });\n }\n return promise;\n };\n ClaraSceneService.prototype.snapshot = function (sceneApi, options) {\n sceneApi.api.commands.setCommandOptions('snapshot', options);\n var result = sceneApi.api.commands.runCommand('snapshot');\n return result;\n };\n ClaraSceneService.prototype.getRootSceneId = function (sceneApi) {\n return sceneApi.api.scene.find({ includeParent: true });\n };\n ClaraSceneService.prototype.frameScene = function (sceneApi, args) {\n var nodeList = args ? [args.node] : null;\n sceneApi.api.player.frameScene(nodeList, args);\n };\n ClaraSceneService.prototype.isHierarchicalVisibilityEnabled = function (sceneApi) {\n var rootSceneId = sceneApi.api.scene.find({ includeParent: true });\n var r = sceneApi.api.scene.get({\n id: rootSceneId,\n plug: \"Properties\",\n property: \"hierarchyVisibility\"\n });\n return r == \"Enable\";\n };\n ClaraSceneService.prototype.ghost = function (sceneApi, args) {\n if (!sceneApi.ghoster) {\n sceneApi.ghoster = sceneApi.api.selection.addGhoster({ opacity: .7 });\n }\n var nodeIds = sceneApi.api.scene.filter({ from: { id: args.id }, includeParent: true });\n nodeIds.forEach(function (n) {\n if (args.on) {\n sceneApi.ghoster.selectionSet.add(n);\n }\n else {\n sceneApi.ghoster.selectionSet.remove(n);\n }\n });\n };\n ClaraSceneService.prototype.highlight = function (sceneApi, args, type) {\n if (!sceneApi.highlighter) {\n sceneApi.highlighter = sceneApi.api.selection.setHighlighting(true, { color: \"#ff0000\", thickness: 2 });\n }\n var nodeIds = sceneApi.api.scene.filter({ from: { id: args.id }, includeParent: true, type: [\"PolyMesh\", \"BinMesh\", /*\"Null\",*/ \"Model\", \"Annotation\", \"Helper\"] });\n var highlighter = sceneApi.highlighter;\n nodeIds.forEach(function (n) {\n if (args.on) {\n highlighter.selectionSet.add(n);\n sceneApi.highlights[type][n] = true;\n }\n else {\n highlighter.selectionSet.remove(n);\n delete sceneApi.highlights[type][n];\n }\n });\n };\n ClaraSceneService.prototype.clearHighlightsOfType = function (sceneApi, type) {\n var types = [exports.eHighlightType.user, exports.eHighlightType.selection, exports.eHighlightType.hover];\n types.remove(type);\n var _loop_1 = function (id) {\n //only remove if the node is not part of another highlight type\n var shouldUnhighlight = !types.some(function (t) { return sceneApi.highlights[t][id]; });\n if (shouldUnhighlight && sceneApi.highlighter) {\n sceneApi.highlighter.selectionSet.remove(id);\n }\n };\n for (var id in sceneApi.highlights[type]) {\n _loop_1(id);\n }\n sceneApi.highlights[type] = {};\n };\n ClaraSceneService.prototype.clearGhosts = function (sceneApi) {\n if (sceneApi.ghoster) {\n sceneApi.ghoster.selectionSet.clear();\n }\n };\n ClaraSceneService.prototype.select = function (sceneApi, args) {\n if (!sceneApi.selector) {\n sceneApi.selector = sceneApi.api.selection.createSelectionSet();\n sceneApi.api.selection.setActiveSelectionSet(sceneApi.selector);\n }\n if (!sceneApi.selectedNodes.contains(args.id)) {\n this.clearSelection(sceneApi);\n sceneApi.selectedNodes.push(args.id);\n sceneApi.selector.add(args.id);\n this.highlight(sceneApi, { id: args.id, on: true }, exports.eHighlightType.selection);\n }\n };\n ClaraSceneService.prototype.deselect = function (sceneApi, nodeId) {\n this.highlight(sceneApi, { id: nodeId, on: false }, exports.eHighlightType.selection);\n sceneApi.selectedNodes.remove(nodeId);\n sceneApi.selector && sceneApi.selector.remove(nodeId);\n };\n ClaraSceneService.prototype.clearSelection = function (sceneApi) {\n for (var i = sceneApi.selectedNodes.length - 1; i >= 0; i--) {\n this.deselect(sceneApi, sceneApi.selectedNodes[i]);\n }\n };\n ClaraSceneService.prototype.getThree = function (sceneApi) {\n return sceneApi.api.player.getThree().THREE;\n };\n ClaraSceneService = __decorate([\n NgService({\n token: Token.ClaraSceneService,\n dependencies: [\n Token.RuleService,\n Token.$Q,\n ]\n })\n ], ClaraSceneService);\n return ClaraSceneService;\n }());\n\n var SceneViewer = /** @class */ (function () {\n function SceneViewer(args) {\n var _this = this;\n this.args = args;\n Object.keys(args).forEach(function (prop) {\n _this[prop] = args[prop];\n });\n this.loadDeferred = this.$q.defer();\n }\n SceneViewer.prototype.loadScene = function (args) {\n // flush out stuff that needs to be flushed\n this.clearHandlers();\n this.$scope.loaded = false;\n this.loadDeferred = this.$q.defer();\n // reset scope\n this.scene = args.scene;\n if (args.isStandalone) {\n //it's a standalone scene, so the uiConfig and sceneConfig are one and the same\n this.sceneConfig = args.config;\n this.uiConfig = args.config;\n this.sceneConfig.$uiConfigurator = args.config;\n }\n else {\n //it's a full cpq config, so we make another configurator just for the scene\n this.sceneConfig = new enums.Configurator(new enums.KbObjectManager(), this.scene.configurator);\n this.sceneConfig.$running = true;\n this.sceneConfig.name = this.scene.name;\n this.sceneConfig.idScene = this.scene.id;\n this.sceneConfig.$uiConfigurator = args.config;\n this.uiConfig = args.config;\n this.uiConfig.$sceneConfigurator = this.sceneConfig; //set the sceneConfigurator in the uiconfig so templates have access to it\n }\n return this.loadSceneInternal(args);\n };\n SceneViewer.prototype.createElem = function () {\n var parentElem = document.querySelector(this.elemSelector);\n this.elem = document.createElement('div');\n this.elem.classList.add('kb-viewer__3d');\n parentElem.appendChild(this.elem);\n };\n SceneViewer.prototype.createHotspotElem = function () {\n // load the hotspot div after the player so it ends up later in the html\n this.hotspotDiv = document.createElement('div');\n this.hotspotDiv.classList.add('kb-viewer__hotspots', 'xr-overlay');\n this.hotspotDiv.setAttribute('ng-include', \"'hotspots-template'\");\n this.hotspotDiv.setAttribute('ng-if', 'loaded');\n this.hotspotDiv.setAttribute('ng-cloak', '');\n this.elem.appendChild(this.hotspotDiv);\n this.hotspotDiv = this.compileTemplate(this.hotspotDiv, this.$scope);\n };\n SceneViewer.prototype.show = function () {\n if (this.elem.classList.contains('kb-hide')) {\n this.elem.classList.remove('kb-hide');\n // redraw otherwise it won't actually show\n this.resize();\n }\n };\n SceneViewer.prototype.hide = function () {\n if (!this.elem.classList.contains('kb-hide')) {\n this.elem.classList.add('kb-hide');\n }\n };\n SceneViewer.prototype.notifyLoaded = function () {\n /* notify any outside pages that are embedding that the scene is loaded.\n We pass the requestid that was passed in as a query string param back to\n them so they know which iframe has been loaded (in case they have multiple\n kbmax iframes on the same page) */\n _tools.Utils.sendMessageToParent({\n name: 'sceneloaded',\n data: {\n requestId: this.requestId,\n },\n });\n _tools.Utils.sendMessageToParent({ name: 'progress', data: 0.2 });\n this.$scope.loaded = true;\n this.loadDeferred.resolve();\n };\n SceneViewer.prototype.runActionRule = function (actionName, ruleArgs) {\n var _this = this;\n var action = this.sceneConfig.actions.find(function (a) { return a.name.isEqual(actionName); });\n if (action) {\n return this.loadDeferred.promise.then(function () {\n return _this.ruleService.runRuleContainerAsync(action, ruleArgs).then(function (r) {\n _this.handleRuleError(action.name + ' ' + action.$type, r);\n return r;\n });\n });\n }\n };\n SceneViewer.prototype.setFieldsIfStandalone = function () {\n // if this is a standalone scene being used with a full CPQ configurator,\n // then we need to set the fields of the scene configurator\n if (this.sceneConfig != this.uiConfig && !this.sceneConfig.idProduct) {\n this.sceneConfig.setFields(this.uiConfig.getFieldsObject());\n }\n };\n SceneViewer.prototype.sendMessage = function (msg) {\n if (this.messageCallback) {\n this.messageCallback(msg);\n }\n // send message to embed consumer\n _tools.Utils.sendMessageToParent(msg);\n };\n SceneViewer.prototype.refreshElementParent = function () {\n //get the first visible viewer element\n var $parent = $(this.elemSelector + ':visible:first');\n if ($parent.length && this.elem && !$parent.find(this.elem).length) {\n $parent[0].appendChild(this.elem);\n }\n };\n SceneViewer.prototype.positionHotspot = function (pos, hotspot) {\n hotspot.$top = pos.y;\n hotspot.$left = pos.x;\n if (hotspot.popupPosition == enums.eHotspotPosition.target) {\n var x = pos.x;\n var y = pos.y;\n if (hotspot.popupAttach == enums.eHotspotAttach.top) {\n y = pos.top;\n }\n else if (hotspot.popupAttach == enums.eHotspotAttach.bottom) {\n y = pos.top + pos.height;\n }\n else if (hotspot.popupAttach == enums.eHotspotAttach.left) {\n x = pos.left;\n }\n else if (hotspot.popupAttach == enums.eHotspotAttach.right) {\n x = pos.left + pos.width;\n }\n else if (hotspot.popupAttach == enums.eHotspotAttach.topLeft) {\n y = pos.top;\n x = pos.left;\n }\n else if (hotspot.popupAttach == enums.eHotspotAttach.topRight) {\n y = pos.top;\n x = pos.left + pos.width;\n }\n else if (hotspot.popupAttach == enums.eHotspotAttach.bottomLeft) {\n y = pos.top + pos.height;\n x = pos.left;\n }\n else if (hotspot.popupAttach == enums.eHotspotAttach.bottomRight) {\n y = pos.top + pos.height;\n x = pos.left + pos.width;\n }\n x += hotspot.popupOffsetX;\n y += hotspot.popupOffsetY;\n if (hotspot.keepPopupInViewer && hotspot.open) {\n var $popup = $('#kb-hotspot__popup-' + hotspot.id);\n var popupHeight = $popup.height();\n var popupWidth = $popup.width();\n if (y < 0)\n y = 0;\n if (y + popupHeight > this.hotspotDiv.clientHeight) {\n y = Math.round(this.hotspotDiv.clientHeight - popupHeight);\n }\n if (x < 0)\n x = 0;\n if (x + popupWidth > this.hotspotDiv.clientWidth) {\n x = Math.round(this.hotspotDiv.clientWidth - popupWidth);\n }\n }\n hotspot.popupTop = y.toString() + 'px';\n hotspot.popupLeft = x.toString() + 'px';\n hotspot.popupRight = 'auto';\n hotspot.popupBottom = 'auto';\n }\n };\n SceneViewer.prototype.getAllHotspots = function () {\n var allHotspots = [];\n var allUiConfigs = [this.uiConfig].concat(this.uiConfig.getAllConfigurators());\n for (var _i = 0, allUiConfigs_1 = allUiConfigs; _i < allUiConfigs_1.length; _i++) {\n var uic = allUiConfigs_1[_i];\n if (uic.$sceneConfigurator && (uic == this.uiConfig || uic.$nestHotspots))\n allHotspots.pushArray(uic.$sceneConfigurator.hotspots);\n }\n return allHotspots;\n };\n return SceneViewer;\n }());\n\n var HandlerDb = /** @class */ (function () {\n function HandlerDb(sceneApi, sceneService) {\n this.sceneApi = sceneApi;\n this.sceneService = sceneService;\n // public byHandler: { [handlerId: string]: T } = {};\n this.byNode = {};\n }\n HandlerDb.prototype.clear = function () {\n // this.byHandler = {};\n this.byNode = {};\n };\n HandlerDb.prototype.clearTransient = function () {\n for (var key in this.byNode) {\n var h = this.byNode[key];\n if (h) {\n var removed = h.removeWhere(function (h1) { return h1.addedByRuleType && h1.addedByRuleType.equalsAny(enums.eRuleType.value, enums.eRuleType.scene); });\n if (removed && removed.length && !h.length) {\n delete this.byNode[key];\n }\n }\n }\n };\n HandlerDb.prototype.addToDb = function (id, handler) {\n if (!this.byNode.hasOwnProperty(id)) {\n this.byNode[id] = [];\n }\n this.byNode[id].push(handler);\n };\n HandlerDb.prototype.add = function (node, handlerId, handler) {\n var _this = this;\n var hotspotId = handler.hotspotId;\n if (hotspotId) {\n //for non-mesh hotspots, we just add the hotspot id to the clickdb\n this.addToDb(hotspotId, handler);\n }\n else {\n var query = this.sceneService.getQueryObject(this.sceneApi, node, null);\n var matchingNodes = this.sceneApi.cache.paths.getIds(query);\n matchingNodes.forEach(function (matchingNode) {\n _this.addToDb(matchingNode, handler);\n });\n }\n //add the node id to map to itself\n // db.nodeMap[args.modelId] = args.modelId;\n //add children of the node to the map\n // this.sceneService.getChildNodeIds(this.sceneApi, args.modelId).forEach(i => db.nodeMap[i] = args.modelId);\n // }\n };\n return HandlerDb;\n }());\n var ClaraSceneRuleArgs = /** @class */ (function () {\n function ClaraSceneRuleArgs(viewer) {\n this.viewer = viewer;\n this.logs = new _rules.ClientLogger();\n this.isMobile = viewer.isMobile;\n }\n // public upload() {\n // return this.viewer.upload();\n // }\n // TODO: remove in future. It's only here for backwards compatibility. It's true place now is in SceneUtilities\n ClaraSceneRuleArgs.prototype.addModelClickHandler = function (args) {\n this.sceneUtils.addModelClickHandler(args);\n };\n ClaraSceneRuleArgs.prototype.addDraggable = function (args) {\n this.sceneUtils.addDraggable(args);\n };\n ClaraSceneRuleArgs.prototype.playSceneAnimation = function (args) {\n // DEPRECATED\n };\n ClaraSceneRuleArgs.prototype.toggleSceneAnimation = function () {\n // DEPRECATED\n };\n ClaraSceneRuleArgs.prototype.sendMessage = function (msg) {\n this.viewer.sendMessage(msg);\n };\n ClaraSceneRuleArgs.prototype.selectPage = function (page) {\n if (this.viewer.navigateToElement) {\n this.viewer.navigateToElement(page);\n }\n };\n ClaraSceneRuleArgs.prototype.convertCurrency = function (obj) {\n return null;\n };\n ClaraSceneRuleArgs.prototype.toggleTool = function (args) {\n this.viewer.sceneService.toggleTool(this.sceneApi, args);\n if (args.tool == \"orbit\") {\n this.viewer.sceneConfig.allowOrbit = args.enabled;\n }\n else if (args.tool == \"pan\") {\n this.viewer.sceneConfig.allowPan = args.enabled;\n }\n else if (args.tool == \"zoom\") {\n this.viewer.sceneConfig.allowZoom = args.enabled;\n }\n };\n ClaraSceneRuleArgs.prototype.constrainCamera = function (args) {\n this.viewer.sceneService.constrainCamera(this.sceneApi, args);\n };\n ClaraSceneRuleArgs.prototype.getUploadImageNode = function (args) {\n var a = this.sceneApi.importedImages[this.configurator.name + \"_\" + args.fieldId];\n return a ? a.imageNodeId : null;\n };\n ClaraSceneRuleArgs.prototype.getTables = function (args) {\n var _this = this;\n return new _rules.KPromise(args.ids.map(function (tid) { return _this.viewer.tableArraysDb[tid]; }));\n };\n return ClaraSceneRuleArgs;\n }());\n var ClaraViewer = /** @class */ (function (_super) {\n __extends(ClaraViewer, _super);\n function ClaraViewer(cArgs) {\n var _this = _super.call(this, cArgs) || this;\n _this.hovers = [];\n /**\n * in the form of {annotationId: hotspotId}\n */\n _this.annotationToHotspotDb = {};\n /**\n * stores what scene Id's we've already prefetched so we don't bother prefetching them again.\n * Once they are prefetched they are in the browser cache.\n */\n _this.prefetchedScenes = {};\n // protected getDragOffset(ev: clara2.IMouseEvent, d: IDraggable): THREE.Vector3 {\n // let three = this.sceneService.getThree(this.sceneApi);\n // let referPoint = new three.Vector3();\n // let offset = new three.Vector3(0, 0, 0);\n // let ray: THREE.Ray = void 0;\n // if (d.mode == eDragMode.plane) {\n // if (ev.eventRay) {\n // ray = ev.eventRay.ray;\n // } /*else {\n // let rect = this.elem.getBoundingClientRect();\n // let ndc = { //normalized device coordinates. x & y should be between -1 and 1\n // x: (2 * ev.clientX - rect.width) / rect.width,\n // y: (rect.height - 2 * ev.clientY) / rect.height\n // };\n // ray = store.getTranslator().getCameraMouseRay(ndc).ray;\n // }*/\n // if (d.mode == eDragMode.plane) {\n // let moveOnPlane = new three.Plane();\n // let moveOnNormal = new three.Vector3();\n // moveOnNormal.set(d.normal.x, d.normal.y, d.normal.z);\n // moveOnPlane.set(moveOnNormal, -(d.distanceFromOrigin || 0)); //plane.constant);\n // if (!ray.intersectsPlane(moveOnPlane)) return;\n // ray.intersectPlane(moveOnPlane, referPoint);\n // }\n // var nodeMatrix = this.sceneApi.api.scene.getWorldTransform(d.$activeNode.id);\n // var nodePosition = new three.Vector3().setFromMatrixPosition(nodeMatrix);\n // offset = referPoint.sub(nodePosition);\n // }\n // return offset;\n // }\n // /** draggables store the nodes they match, but since they support regex too, at some point we need to run those searches to find the matching nodes to compare against for mouse events */\n // protected fillDraggables() {\n // let sceneApi = this.sceneApi;\n // for (let d of sceneApi.draggables) {\n // //get all of the matching node id's to the query provided, and cache for fast retrieval\n // if (!d.$matchingNodes) {\n // d.$matchingNodes = {};\n // let query = this.sceneService.getQueryObject(sceneApi, d.objectId, d.name);\n // sceneApi.cache.paths.getIds(query).forEach(id => d.$matchingNodes[id] = {});\n // //also get all of the children of the matching nodes\n // // for (let mid in d.$matchingNodes) {\n // // sceneApi.cache.paths.getIds({ from: mid }).forEach(id => d.$matchingNodes[mid][id] = null);\n // // }\n // }\n // }\n // }\n _this._clickAlreadyHandled = false; //during drags, the mousedown might initiate the click event. We mark whether it has, so the click handler can ignore.\n _this.hotspotCounter = 0;\n _this.processingMouseOver = false;\n _this.sceneService = cArgs.sceneService;\n _this.playerUrl = cArgs.playerUrl;\n _this.ocLazyLoad = cArgs.ocLazyLoad;\n _this.sceneApi = {\n isMobile: cArgs.isMobile,\n isRender: _this.isRender,\n clientLanguage: cArgs.clientLanguage,\n sceneDb: cArgs.sceneDb,\n onSceneNested: function (nested, nodeId) { return _this.onSceneNested(nested, nodeId); },\n afterSetProperty: function (setArgs) { return _this.afterSetProperty(setArgs); },\n afterAnimateProperty: function (setArgs) { return _this.afterAnimateProperty(setArgs); },\n addModelClickHandler: function (args) { return _this.sceneApi.clickDb.add(args.modelId, args.uniqueId, args); },\n clearClickHandlers: function () { return _this.sceneApi.clickDb = new HandlerDb(_this.sceneApi, _this.sceneService); },\n addDraggable: function (args) { return _this.sceneApi.draggableDb.add(args.objectId, args.uniqueId, args); },\n clearDraggables: function () { return _this.sceneApi.draggableDb = new HandlerDb(_this.sceneApi, _this.sceneService); },\n sendMessage: function (msg) { return _this.sendMessage(msg); },\n fetchedScenes: {},\n importedImages: {},\n getTables: function (args) { return new _rules.KPromise(args.ids.map(function (tid) { return _this.tableArraysDb[tid]; })); },\n cameraAnimationInProgress: false,\n // cameraAnimationPromise: new KPromise(null)\n highlights: { user: {}, hover: {}, selection: {} },\n selectedNodes: []\n };\n _this.sceneApi.clickDb = new HandlerDb(_this.sceneApi, _this.sceneService);\n _this.sceneApi.draggableDb = new HandlerDb(_this.sceneApi, _this.sceneService);\n _this.sceneApi.cache = new SceneCache(_this.sceneApi);\n //this.$scope = this.controllerScope.$new();\n _this.$scope.hotspotClick = function ($event, ann) { return _this.hotspotClick($event, ann); };\n _this.$scope.hotspotCloseClick = function ($event, ann) { return _this.hotspotCloseClick($event, ann); };\n // this.$scope.vrMode = false;\n // this.$scope.toggleVrMode = () => this.toggleVrMode();\n // this.$scope.arMode = false;\n // this.$scope.toggleArMode = () => this.toggleArMode();\n _tools.Utils.supportsVr().then(function (res) { return _this.$scope.supportsVr = res; });\n _this.$scope.allHotspots = [];\n return _this;\n }\n ClaraViewer.detectWebGL = function () {\n try {\n var canvas = document.createElement(\"canvas\");\n return !!(window.WebGLRenderingContext &&\n (canvas.getContext(\"webgl\") || canvas.getContext(\"experimental-webgl\")));\n }\n catch (e) {\n return false;\n }\n };\n ClaraViewer.prototype.init = function () {\n var _this = this;\n return this.ocLazyLoad.load(this.playerUrl).then(function () {\n // initialize clara viewer\n _this.createElem();\n var api = claraplayer(_this.elem);\n _this.sceneApi.api = api;\n [\"orbit\", \"pan\", \"zoom\", \"home\", \"fullscreen\", \"vrSettings\", \"arMode\"].forEach(function (s) {\n return api.player.hideTool(s);\n }); // hide the icons \n api.player.removeTool(\"select\");\n // turn off the thumbnail\n api.player.displayThumbnail(false);\n // setup highlighting\n _this.sceneApi.highlighter = api.selection.setHighlighting(true, { color: _this.highlightColor, thickness: 2 });\n /* we use both the customAnnotationFn (for when a hotspot is tied to an annotation) and\n useCustomOverlay for hotspots that are tied to other types of nodes.\n We can't use useCustomOverlay for both because annotations aren't loaded into the scene\n and getScenePosition(idAnnotation) won't work as a result */\n api.annotations.useCustomAnnotationFunction(function (a, d) { return _this.annotationFn(a, d); });\n api.annotations.useCustomOverlayFunction(function (d) { return _this.customOverlayFn(d); });\n _this.createHotspotElem();\n // add click event\n api.player.addTool({\n click: function (event) { return _this.click(event); }\n }, \"ComponentClick\");\n // add hover event\n api.player.addTool({\n hover: function (event) { return _this.hover(event); }\n }, \"Hover\");\n // add hover event\n api.player.addTool({\n mousedown: function (event) { return _this.mousedown(event); }\n }, \"Mousedown\");\n });\n };\n ClaraViewer.prototype.loadSceneInternal = function (loadSceneArgs) {\n var _this = this;\n // flush out stuff that needs to be flushed\n this.clearHandlers();\n this.annotationToHotspotDb = {};\n this.sceneApi.cache = new SceneCache(this.sceneApi);\n this.sceneApi.highlights = { user: {}, hover: {}, selection: {} };\n this.sceneApi.selectedNodes = [];\n var api = this.sceneApi.api;\n if (loadSceneArgs.clearMemory) {\n this.sceneApi.api.sceneIO.clearScene();\n this.sceneApi.fetchedScenes = {}; // clear out the fetched scenes since they were just cleared out of memory\n this.sceneApi.importedImages = {};\n }\n // toggle tools based on initial scene configurator properties\n this.toggleTools();\n if (this.sceneConfig.constrainCameraToRadius) {\n this.sceneService.constrainCamera(this.sceneApi, {\n constrain: this.sceneConfig.constrainCameraToRadius,\n radius: this.sceneConfig.cameraRadius\n });\n }\n // 'rendered' event is when the loading animation is done - we might want to use this when clearing memory\n // new loading animation too\n // turn thumbnail off with displayThumbnail in player\n var rulesRun = false; // to get around a bug in clara where resize causes the loaded event to fire\n api.on(\"loaded\", function () {\n if (!rulesRun) {\n rulesRun = true;\n _this.sceneApi.hierarchicalVisibility = _this.sceneService.isHierarchicalVisibilityEnabled(_this.sceneApi);\n _this.shimThree(_this.sceneApi);\n _this.runLoadedRule(_this.getRuleArgs(enums.eRuleType.sceneLoaded)).then(function () {\n if (_this.sceneApi.api.commands.isCommandEnabled) {\n // need to check armode here because it's calculation is delayed\n _this.$scope.arEnabled = _this.sceneApi.api.commands.isCommandEnabled(\"arMode\");\n }\n _this.$timeout(function () { return _this.resize(); }, 0);\n // prefetch all scenes so that nested scenes and d&d components load faster\n _this.prefetchScenes(_this.sceneApi);\n });\n }\n });\n this.sceneApi.fetchedScenes[this.sceneConfig.claraId] = api.sceneIO.fetchAndUse(this.sceneConfig.claraId, this.scene.publishHash, { waitForPublish: true });\n this.prefetchedScenes[this.sceneConfig.claraId] = null;\n return this.loadDeferred.promise;\n };\n ClaraViewer.prototype.toggleTools = function () {\n // toggle tools based on initial scene configurator properties\n this.sceneService.toggleTool(this.sceneApi, { tool: \"orbit\", enabled: this.sceneConfig.allowOrbit });\n this.sceneService.toggleTool(this.sceneApi, { tool: \"pan\", enabled: this.sceneConfig.allowPan });\n this.sceneService.toggleTool(this.sceneApi, { tool: \"zoom\", enabled: this.sceneConfig.allowZoom });\n if (this.sceneConfig.allowOrbit)\n this.sceneApi.api.commands.activateCommand(\"orbit\");\n else if (this.sceneConfig.allowPan)\n this.sceneApi.api.commands.activateCommand(\"pan\");\n else if (this.sceneConfig.allowZoom)\n this.sceneApi.api.commands.activateCommand(\"zoom\");\n };\n ClaraViewer.prototype.runLoadedRule = function (ruleArgs) {\n var _this = this;\n // run the loaded rule of the scene\n this.setFieldsIfStandalone();\n return this.ruleService.runRuleTypeAsync(this.sceneConfig, enums.eRuleType.sceneLoaded, ruleArgs).then(function (loadedRuleResult) {\n _this.handleRuleError(enums.eRuleType.sceneLoaded, loadedRuleResult);\n return _this.runRules(false).then(function () {\n _this.notifyLoaded();\n });\n });\n };\n ClaraViewer.prototype.mousedown = function (event) {\n var _this = this;\n var sceneApi = this.sceneApi;\n var api = sceneApi.api;\n this._clickAlreadyHandled = false;\n //search for draggables\n if (Object.keys(sceneApi.draggableDb.byNode).length) {\n // this.fillDraggables();\n var hits = this.currentFilterNodes = api.player.filterNodesFromPosition(event);\n var hit = hits.first();\n var activeDrag_1 = null;\n var activeNodeId_1 = this.sceneService.findAncestorNodeId(this.sceneApi, hit, function (nid) {\n activeDrag_1 = sceneApi.draggableDb.byNode[nid] ? sceneApi.draggableDb.byNode[nid].first() : null;\n return activeDrag_1 != null;\n });\n if (activeDrag_1) {\n //ok we have an active drag, so we select the node\n this.sceneService.select(sceneApi, { id: activeNodeId_1 });\n var dragStarted_1 = false;\n var sceneUtils = this.sceneService.getSceneUtilities(sceneApi, enums.eRuleType.scene, {}, null);\n var dragNode_1 = activeDrag_1.$activeNode = sceneUtils.getNode({ id: activeNodeId_1 });\n var three_1 = this.sceneService.getThree(sceneApi);\n var startPos_1 = (new three_1.Vector3()).setFromMatrixPosition(api.scene.getWorldTransform(activeNodeId_1));\n // let offset = this.getDragOffset(event, activeDrag);\n //console.log({ event: \"beforeDrag\", x: startPos.x, y: startPos.y, z: startPos.z });\n //and we start the nodeMove command so they can drag it\n api.commands.setCommandOptions('nodeMove', {\n displayGizmo: false,\n mode: activeDrag_1.mode,\n plane: activeDrag_1.mode == enums.eDragMode.plane ? { normal: activeDrag_1.normal, constant: activeDrag_1.distanceFromOrigin ? -activeDrag_1.distanceFromOrigin : 0 } : null,\n surfaceNodeIds: activeDrag_1.mode == enums.eDragMode.surface ? (Array.isArray(activeDrag_1.surfaceNodes) ? activeDrag_1.surfaceNodes : [activeDrag_1.surfaceNodes]) : null,\n keepOffset: true,\n shouldMove: function (event, newPos, data) {\n // offset && newPos.sub(offset); // temp fix for clara bug: https://github.com/Exocortex/ExocortexKBMax/issues/208\n var hitData = data ? data.first() : null;\n var uv = hitData ? hitData.uv : null;\n var args = { dragNode: dragNode_1, startPos: startPos_1, newPos: newPos, allow: true, relativeSurfacePos: uv };\n if (!dragStarted_1) {\n dragStarted_1 = true;\n activeDrag_1.dragStart && activeDrag_1.dragStart(args);\n //console.log({ event: \"dragStart\", x: args.newPos.x, y: args.newPos.y, z: args.newPos.z });\n }\n if (activeDrag_1.dragging && dragStarted_1) {\n activeDrag_1.dragging(args);\n //console.log({ event: \"dragging\", x: args.newPos.x, y: args.newPos.y, z: args.newPos.z });\n }\n // offset && newPos.add(offset); // temp fix for clara bug: https://github.com/Exocortex/ExocortexKBMax/issues/208\n return args.allow;\n },\n // updatePosition: (newPos, surface) => {\n // newPos.sub(offset); // temp fix for clara bug: https://github.com/Exocortex/ExocortexKBMax/issues/208\n // let args = { dragNode, startPos, newPos } as IDragArgs;\n // if (activeDrag.dragging) {\n // activeDrag.dragging(args);\n // }\n // newPos.add(offset); // temp fix for clara bug: https://github.com/Exocortex/ExocortexKBMax/issues/208\n // },\n onEnd: function (event) {\n _this.$timeout(function () {\n //if the drag never started, then we don't have a drop event\n if (dragStarted_1) {\n var args = { dragNode: dragNode_1, allow: true, startPos: startPos_1, newPos: (new three_1.Vector3()).setFromMatrixPosition(api.scene.getWorldTransform(activeNodeId_1)), relativeSurfacePos: null };\n activeDrag_1.dropped && activeDrag_1.dropped(args);\n //console.log({ event: \"dropped\", x: args.newPos.x, y: args.newPos.y, z: args.newPos.z });\n }\n _this.toggleTools();\n sceneApi.activeDrag = null;\n _this.click(event);\n });\n }\n });\n api.commands.runCommand(\"nodeMove\");\n }\n else {\n this.sceneService.clearSelection(sceneApi);\n this.toggleTools();\n sceneApi.activeDrag = null;\n }\n }\n };\n ClaraViewer.prototype.click = function (event) {\n var _this = this;\n if (!this._clickAlreadyHandled) {\n this._clickAlreadyHandled = true;\n this.$timeout(function () {\n _this.clearAnnotations();\n var db = _this.sceneApi.clickDb;\n //let idsToFilterBy = Object.keys(db.nodeMap);\n var nodeIds = _this.currentFilterNodes || _this.sceneApi.api.player.filterNodesFromPosition(event /*, null, { nodes: idsToFilterBy }*/);\n //clear out our stored results\n _this.currentFilterNodes = null;\n if (nodeIds && nodeIds.length) {\n var nodeId = nodeIds[0];\n if (db) {\n // check if this node or any of it's parents have a click event\n var parentId = nodeId;\n var _loop_1 = function () {\n if (db.byNode.hasOwnProperty(parentId)) {\n var sceneUtils = _this.sceneService.getSceneUtilities(_this.sceneApi, enums.eRuleType.scene, {}, null);\n var clickArgs_1 = { clickedNode: sceneUtils.getNode({ id: parentId }), propogate: false };\n db.byNode[parentId].forEach(function (h) { return h.handler(clickArgs_1); });\n if (!clickArgs_1.propogate)\n return \"break\";\n }\n parentId = _this.sceneService.getParentNodeId(_this.sceneApi, parentId);\n };\n while (parentId) {\n var state_1 = _loop_1();\n if (state_1 === \"break\")\n break;\n }\n }\n }\n else {\n //empty space was clicked. See if there was a handler put on the root scene node\n var rootSceneId = _this.sceneService.getRootSceneId(_this.sceneApi);\n if (db.byNode.hasOwnProperty(rootSceneId)) {\n var sceneUtils = _this.sceneService.getSceneUtilities(_this.sceneApi, enums.eRuleType.scene, {}, null);\n var clickArgs_2 = { clickedNode: sceneUtils.getNode({ id: rootSceneId }), propogate: false };\n db.byNode[rootSceneId].forEach(function (h) { return h.handler(clickArgs_2); });\n }\n }\n });\n }\n };\n ClaraViewer.prototype.hover = function (event) {\n var clickdb = this.sceneApi.clickDb;\n var dragdb = this.sceneApi.draggableDb;\n if ((Object.keys(clickdb.byNode).length || Object.keys(dragdb.byNode).length) && !this.sceneApi.cameraAnimationInProgress && !this.sceneApi.activeDrag) {\n if (this.processingMouseOver)\n return;\n this.processingMouseOver = true;\n //let idsToFilterBy = Object.keys(db.nodeMap);\n var nodeIds = this.sceneApi.api.player.filterNodesFromPosition(event /*, null, { nodes: idsToFilterBy }*/);\n if (nodeIds && nodeIds.length) {\n var nodeId = nodeIds[0];\n // find the closest ancestor node with a click handler on it\n var hoverParentId = this.sceneService.findAncestorNodeId(this.sceneApi, nodeId, function (nid) { return (clickdb.byNode.hasOwnProperty(nid) || dragdb.byNode.hasOwnProperty(nid)); });\n if (hoverParentId) {\n if (this.hoverParentId != hoverParentId) {\n this.clearMouseOver();\n this.hoverParentId = hoverParentId;\n // now we have the parent that has the click handler. \n // The parent and all of it's children should have their materials changed\n this.setMouseOverEffectRecursive(this.sceneApi, hoverParentId);\n var handlers = clickdb.byNode[hoverParentId];\n handlers && handlers.forEach(function (arg) {\n if (arg.hotspot)\n arg.hotspot.$hover = true;\n });\n }\n }\n else {\n this.clearMouseOver();\n }\n }\n else {\n this.clearMouseOver();\n }\n this.processingMouseOver = false;\n }\n else {\n this.clearMouseOver();\n }\n };\n ClaraViewer.prototype.shimThree = function (sceneApi) {\n var three = sceneApi.api.player.getThree().THREE;\n if (!three.$originalUpdateMatrixWorld) {\n var umw = three.$originalUpdateMatrixWorld = three.Object3D.prototype.updateMatrixWorld;\n }\n if (sceneApi.hierarchicalVisibility) {\n //THREE traverses from parent down updating the matrix world on every pass\n //But it doesn't pay attention to hierarchical visibility\n three.Object3D.prototype.updateMatrixWorld = function (force) {\n if (!this.visible)\n return;\n three.$originalUpdateMatrixWorld.apply(this, arguments);\n };\n }\n else {\n three.Object3D.prototype.updateMatrixWorld = three.$originalUpdateMatrixWorld;\n }\n /** override updateMatrix to add in a cache for the matrix vectors, so\n * we're only rebuilding it when we have to. Makes a big difference on render frame rates\n */\n three.Object3D.prototype.updateMatrix = function () {\n var createdCache = false;\n if (!this._positionCache) {\n this._positionCache = new three.Vector3();\n this._quaternionCache = new three.Quaternion();\n this._scaleCache = new three.Vector3(1, 1, 1);\n this._visibleCache = this.visible;\n createdCache = true;\n }\n if (createdCache ||\n (!this._positionCache.equals(this.position)\n || !this._quaternionCache.equals(this.quaternion)\n || !this._scaleCache.equals(this.scale)\n || this.visible != this._visibleCache)) {\n this.matrix.compose(this.position, this.quaternion, this.scale);\n this.matrixWorldNeedsUpdate = true;\n this._positionCache.copy(this.position);\n this._quaternionCache.copy(this.quaternion);\n this._scaleCache.copy(this.scale);\n this._visibleCache = this.visible;\n }\n };\n };\n ClaraViewer.prototype.prefetchScenes = function (sceneApi) {\n var _this = this;\n Object.keys(sceneApi.sceneDb).forEach(function (idScene) {\n if (!_this.prefetchedScenes.hasOwnProperty(sceneApi.sceneDb[idScene].claraId)) {\n _this.prefetchedScenes[sceneApi.sceneDb[idScene].claraId] = null;\n sceneApi.api.sceneIO.prefetch(sceneApi.sceneDb[idScene].claraId, sceneApi.sceneDb[idScene].publishHash, { waitForPublish: true });\n }\n });\n };\n ClaraViewer.prototype.getRuleArgs = function (ruleType) {\n var args = new ClaraSceneRuleArgs(this);\n args.configurator = this.sceneConfig.idProduct ? this.uiConfig : this.sceneConfig;\n args.kom = args.configurator.$manager;\n args.parentKom = args.configurator.$parentConfigurator ? args.configurator.$parentConfigurator.$manager : null;\n args.sceneKom = this.sceneConfig.$manager;\n args.sceneApi = this.sceneApi;\n args.isRender = this.isRender;\n args.sceneUtils = this.sceneService.getSceneUtilities(this.sceneApi, ruleType);\n args.clientLanguage = this.clientLanguage;\n return args;\n };\n ClaraViewer.prototype.resolveHotspotTargetNode = function (hotspot) {\n var idMap = hotspot.$parentConfigurator.$sceneIdMap;\n var targetNode = hotspot.targetNode;\n if (idMap) {\n targetNode = idMap[hotspot.targetNode] || hotspot.targetNode;\n }\n return targetNode;\n };\n ClaraViewer.prototype.customOverlayFn = function (div) {\n var _this = this;\n var db = this.sceneApi.clickDb;\n var hotspotProcessed = false;\n var _loop_2 = function (hotspot) {\n if (hotspot.target && hotspot.targetNode && hotspot.visible) {\n hotspotProcessed = true;\n var resolvedTargetNode = this_1.resolveHotspotTargetNode(hotspot);\n var pos = this_1.sceneApi.api.scene.getScreenPosition(resolvedTargetNode);\n if (pos) {\n this_1.positionHotspot(pos, hotspot);\n }\n if (hotspot.targetShape == enums.eHotspotShape.mesh && resolvedTargetNode) {\n if (!db.byNode.hasOwnProperty(resolvedTargetNode) || !db.byNode[resolvedTargetNode].some(function (h) { return h.hotspot == hotspot; })) {\n this_1.sceneApi.addModelClickHandler({\n modelId: resolvedTargetNode,\n uniqueId: hotspot.$uid,\n handler: function () { return _this.hotspotClick({}, hotspot); },\n hotspot: hotspot\n });\n }\n }\n }\n if (hotspot.targetShape == enums.eHotspotShape.mesh && !hotspot.visible) {\n var resolvedTargetNode = this_1.resolveHotspotTargetNode(hotspot);\n // remove from click db if the hotspot is invisible\n if (resolvedTargetNode) {\n if (db.byNode[resolvedTargetNode]) {\n db.byNode[resolvedTargetNode].removeWhere(function (a) { return a.uniqueId == hotspot.$uid; });\n if (db.byNode[resolvedTargetNode].length == 0) {\n delete db.byNode[resolvedTargetNode];\n }\n }\n }\n }\n };\n var this_1 = this;\n for (var _i = 0, _a = this.$scope.allHotspots; _i < _a.length; _i++) {\n var hotspot = _a[_i];\n _loop_2(hotspot);\n }\n // call digest manually on this scope instead of scope.$apply because $apply starts \n // at the root and digests everything.We only want to affect the hotspots here.\n if (hotspotProcessed) { //this can be expensive, so only run if there is something to update\n this.$scope.$digest();\n }\n };\n ClaraViewer.prototype.annotationFn = function (annotation, div) {\n // we don't call scope.$apply here because it's too slow, and the scope.$apply \n // in the customOverlayFn takes care of making sure everything is updated anyways.\n // it's better in the customOverlay because that is only called once per global update, \n // whereas this is called once for each annotation.\n // find the hotspot\n var hotspot = this.annotationToHotspotDb[annotation.id];\n // if it's an orphan annotation, then stop searching for it\n if (!hotspot && !this.annotationToHotspotDb.hasOwnProperty(annotation.id)) {\n hotspot = this.$scope.allHotspots.find(function (h) { return h.targetNode == annotation.id; });\n this.annotationToHotspotDb[annotation.id] = hotspot;\n }\n if (hotspot) {\n hotspot.alpha = annotation.alpha;\n var pos = {\n x: annotation.left,\n y: annotation.top,\n top: annotation.top,\n left: annotation.left,\n width: 0,\n height: 0\n };\n this.positionHotspot(pos, hotspot);\n }\n };\n ClaraViewer.prototype.hotspotClick = function ($event, hotspot) {\n var _this = this;\n hotspot.open = true;\n this.hotspotCounter++;\n hotspot.$zindex = this.hotspotCounter;\n if (hotspot.idCamera) {\n this.sceneService.animateCamera(this.sceneApi, {\n duration: hotspot.animationDuration,\n toCameraId: hotspot.idCamera,\n easing: hotspot.animationEasing\n });\n }\n var clickDb = this.sceneApi.clickDb;\n if (clickDb) {\n var nestedNullId = hotspot.$parentConfigurator.$uiConfigurator.$nestedSceneId;\n var handlerId = nestedNullId ? nestedNullId + \"-\" + hotspot.id : hotspot.id;\n if (clickDb.byNode.hasOwnProperty(handlerId)) {\n var clickArgs_3 = { propogate: false };\n clickDb.byNode[handlerId].forEach(function (h) { return h.handler(clickArgs_3); });\n }\n }\n // some hotspot popups start off the screen because the height can't be calculated until it's shown\n // so we need to offload to recalculate the hotspot position after the digest\n this.$timeout(function () {\n var pos = _this.sceneApi.api.scene.getScreenPosition(_this.resolveHotspotTargetNode(hotspot));\n if (pos) {\n _this.positionHotspot(pos, hotspot);\n }\n });\n };\n ClaraViewer.prototype.hotspotCloseClick = function ($event, hotspot) {\n $event.stopPropagation();\n hotspot.open = false;\n };\n ClaraViewer.prototype.clearAnnotations = function () {\n for (var _i = 0, _a = this.$scope.allHotspots; _i < _a.length; _i++) {\n var h = _a[_i];\n if (h.target && h.allowClose) {\n h.open = false;\n }\n }\n };\n // protected toggleVrMode() {\n // if (this.$scope.vrMode) {\n // this.sceneApi.api.commands.deactivateCommand(\"vrMode\");\n // } else {\n // this.sceneApi.api.commands.activateCommand(\"vrMode\");\n // }\n // }\n // protected toggleArMode() {\n // if (this.$scope.vrMode) {\n // this.sceneApi.api.commands.deactivateCommand(\"arMode\");\n // } else {\n // this.sceneApi.api.commands.runCommand(\"arMode\");\n // // this.sceneApi.api.commands.activateCommand(\"arMode\");\n // }\n // }\n ClaraViewer.prototype.afterSetProperty = function (setArgs) {\n // if (setArgs.plug.isEqual(\"material\") && setArgs.operator.isEqual(\"physical\")) {\n // let mouseOverMatId = this.hoverMaterialDb.get(setArgs.objectId);\n // if (mouseOverMatId) {\n // setArgs.objectId = mouseOverMatId;\n // this.sceneService.setProperty(this.sceneApi, setArgs);\n // }\n // }\n };\n ClaraViewer.prototype.afterAnimateProperty = function (animateArgs) {\n // if (animateArgs.plug.isEqual(\"material\") && animateArgs.operator.isEqual(\"physical\")) {\n // let mouseOverMatId = this.hoverMaterialDb.get(animateArgs.objectId);\n // if (mouseOverMatId) {\n // animateArgs.objectId = mouseOverMatId;\n // this.sceneService.animate(this.sceneApi, animateArgs);\n // }\n // }\n };\n ClaraViewer.prototype.onSceneNested = function (nestedConfig, nullNodeId) {\n var _this = this;\n // setup auto click to select page\n if (nestedConfig.$parentConfigurator.nestedSceneClickToSelect) {\n this.sceneApi.addModelClickHandler({\n modelId: nullNodeId,\n uniqueId: _tools.Utils.shortId(),\n handler: function () {\n _this.navigateToElement(nestedConfig);\n }\n });\n }\n };\n ClaraViewer.prototype.clearHandlers = function () {\n this.sceneApi.draggableDb && this.sceneApi.draggableDb.clear();\n this.sceneApi.clickDb && this.sceneApi.clickDb.clear();\n };\n ClaraViewer.prototype.clearMouseOver = function () {\n // clear out old mouse over\n this.sceneService.clearHighlightsOfType(this.sceneApi, exports.eHighlightType.hover);\n this.hovers.clear();\n this.hoverParentId = null;\n this.elem.style.cursor = \"default\";\n for (var _i = 0, _a = this.$scope.allHotspots; _i < _a.length; _i++) {\n var h = _a[_i];\n h.$hover = false;\n }\n };\n // TODO: remove this\n ClaraViewer.prototype.findAncestorNode = function (node, callback) {\n var parent = node;\n while (parent) {\n if (callback(parent))\n break;\n parent = parent.parentNode();\n }\n return parent;\n };\n ClaraViewer.prototype.setMouseOverEffectRecursive = function (sceneApi, nodeId) {\n if (nodeId) {\n var api = sceneApi.api;\n var nodeType = api.scene.get({ id: nodeId, property: \"type\" });\n this.hovers.push({ nodeId: nodeId });\n this.sceneService.highlight(sceneApi, { id: nodeId, on: true }, exports.eHighlightType.hover);\n this.elem.style.cursor = \"pointer\";\n }\n };\n // public addModelClickHandler(args: IAddModelClickHandlerArgs) {\n // let db = this.sceneApi.clickDb;\n // // only add it to the list of handlers if the id doesn't already have a handler associated\n // if (!db.byHandler.hasOwnProperty(args.uniqueId)) {\n // db.byHandler[args.uniqueId] = args;\n // // get all nodes that match the given query\n // let query = this.sceneService.getQueryObject(this.sceneApi, args.modelId, null);\n // let matchingNodes = this.sceneApi.cache.paths.getIds(query);\n // matchingNodes.forEach(matchingNode => {\n // if (!db.byNode.hasOwnProperty(matchingNode)) {\n // db.byNode[matchingNode] = [];\n // }\n // db.byNode[matchingNode].push(args);\n // });\n // //add the node id to map to itself\n // // db.nodeMap[args.modelId] = args.modelId;\n // //add children of the node to the map\n // // this.sceneService.getChildNodeIds(this.sceneApi, args.modelId).forEach(i => db.nodeMap[i] = args.modelId);\n // }\n // }\n // public addDraggable(d: IDraggable) {\n // let sceneApi = this.sceneApi;\n // d.$matchingNodes = {};\n // let query = this.sceneService.getQueryObject(sceneApi, d.objectId, d.name);\n // sceneApi.cache.paths.getIds(query).forEach(id => d.$matchingNodes[id] = {});\n // }\n ClaraViewer.prototype.resize = function () {\n if (this.$scope.loaded) {\n this.sceneApi.api.player.resize();\n }\n };\n // public upload(): ng.IPromise {\n // // without streamchanges, the upload needs to do the following:\n // // 1. Upload the file to kbmax server\n // // 2. kbmax server imports the file to a public scene in clara that is strictly for uploads\n // // 3. now our client makes a call to importNode into this scene\n // // 4. in the callback of importNode, we can finally get back to the rule with the uploaded file\n // return this.uploadService.promptUserToChooseFile().then(file => {\n // // post the upload to kbmax\n // let url = \"api/scenes/upload\";\n // let postConfig: ng.IRequestShortcutConfig = {\n // transformRequest: angular.identity, // add this to not serialize form data\n // // set header to undefined so the browser sets the multipart content type\n // headers: { \"Content-Type\": undefined }\n // };\n // let formData = new FormData();\n // formData.append(\"file\", file, file.name);\n // let deferred = this.$q.defer();\n // // post the file\n // this.$http.post(url, formData, postConfig).then(response => {\n // // returns the filename of the new node in the upload scene\n // let uploadResult = response.data;\n // // now we need to import the file node from the upload scene into this scene\n // clara(\"importNode\", {\n // el: this.elem,\n // importSceneId: uploadResult.uploadSceneId,\n // importSelector: uploadResult.filename,\n // parentId: \"%MaterialLibrary\",\n // callback: (err, uploadedNode) => {\n // if (err) {\n // deferred.reject(err);\n // } else {\n // deferred.resolve(uploadResult.filename);\n // }\n // }\n // } as clara.IImportNodeCommandConfig);\n // }, reason => {\n // deferred.reject(reason);\n // });\n // // alert the user the file is uploading\n // this.dialogService && this.dialogService.alert({\n // msg: \"Uploading file '\" + file.name + \"'\",\n // successMsg: \"'\" + file.name + \"' uploaded successfully\",\n // promise: deferred.promise\n // });\n // return deferred.promise;\n // });\n // }\n ClaraViewer.prototype.runAction = function (actionName) {\n var args = this.getRuleArgs(enums.eRuleType.action);\n return this.runActionRule(actionName, args);\n };\n ClaraViewer.prototype.runFieldAction = function (elem) {\n var _this = this;\n var args = this.getRuleArgs(enums.eRuleType.field);\n return this.ruleService.runRuleContainerAsync(elem, args).then(function (res) {\n _this.handleRuleError(elem.name + \" \" + elem.$type, res);\n return res;\n });\n };\n ClaraViewer.prototype.runRules = function (waitForLoad) {\n var _this = this;\n if (waitForLoad === void 0) { waitForLoad = true; }\n var promise = waitForLoad ? this.loadDeferred.promise : new _rules.KPromise(null);\n return promise.then(function () {\n _this.setFieldsIfStandalone();\n return _this.sceneService.runRulesCycle(_this.sceneConfig, _this.uiConfig, _this.getRuleArgs(enums.eRuleType.scene))\n .then(function (result) {\n _this.sceneService.deleteOrphanedNestedScenes(_this.sceneApi, _this.uiConfig);\n _this.handleRuleError(enums.eRuleType.scene, result);\n //recalculate all hotspots\n _this.$scope.allHotspots = _this.getAllHotspots();\n return result;\n });\n });\n };\n ClaraViewer.prototype.importUploadFieldImage = function (uiConfig, field, file) {\n return this.sceneService.importUploadFieldImage(this.sceneApi, uiConfig, field, file);\n };\n ClaraViewer.prototype.snapshot = function (options) {\n return new _rules.KPromise(this.sceneService.snapshot(this.sceneApi, options));\n };\n ClaraViewer.prototype.dispose = function () {\n if (this.elem) {\n this.elem.remove();\n this.elem = null;\n }\n };\n return ClaraViewer;\n }(SceneViewer));\n\n /**\n * NOT meant to be used as an angular singleton service. It's a helper for running configurators\n */\n var ConfiguratorHelper = /** @class */ (function () {\n function ConfiguratorHelper(args) {\n this.args = args;\n this.filterLevelDb = {};\n /** once the tablespromise resolves, will be filled with the tables converted to arrays\n * (for sending in to the rule args)\n */\n this.tableArraysDb = {};\n this._optionFilterRunCount = 0;\n }\n ConfiguratorHelper.prototype.downloadTables = function (tableIds) {\n var _this = this;\n if (tableIds.length) {\n return this.args.api.tables.getBatch({ ids: tableIds }, this.args.tracker).then(function (data) {\n _this.loadTables(data);\n });\n }\n else {\n return this.args.$q.when(null);\n }\n };\n ConfiguratorHelper.prototype.loadTables = function (itables) {\n var _this = this;\n itables.forEach(function (t) {\n var table = new enums.Table(t);\n _this.tableArraysDb[table.id] = table.toObjectArray();\n });\n };\n ConfiguratorHelper.prototype.handleRuleError = function (ruleName, result) {\n if (result && result.hasError && this.args.showErrors()) {\n var dialogScope = this.args.$rootScope.$new();\n dialogScope.ruleName = ruleName;\n dialogScope.configuratorName = result.parameters.configurator.name;\n dialogScope.error = result.error.message;\n this.args.dialogService.alert({\n type: enums.eAlertType.error,\n template: Dirs.view(\"alert-rule-error\"),\n scope: dialogScope,\n persist: true\n });\n }\n };\n ConfiguratorHelper.prototype.runRuleContainerAsync = function (ruleContainer, args) {\n var _this = this;\n console.log('run rule async', ruleContainer);\n return this.args.ruleService.runRuleContainerAsync(ruleContainer, args || this.args.getRuleArgs(ruleContainer.$parentConfigurator)).then(function (res) {\n _this.handleRuleError(ruleContainer.name + \" \" + ruleContainer.$type, res);\n return res;\n });\n };\n ConfiguratorHelper.prototype.runRuleContainerSync = function (ruleContainer, args) {\n var res = this.args.ruleService.runRuleContainerSync(ruleContainer, args || this.args.getRuleArgs(ruleContainer.$parentConfigurator));\n this.handleRuleError(ruleContainer.name + \" \" + ruleContainer.$type, res);\n return res;\n };\n ConfiguratorHelper.prototype.runRuleTypeAsync = function (config, ruleType, args) {\n var _this = this;\n return this.args.ruleService.runRuleTypeAsync(config, ruleType, args || this.args.getRuleArgs(config)).then(function (res) {\n _this.handleRuleError(ruleType, res);\n return res;\n });\n };\n ConfiguratorHelper.prototype.runActionByIdAsync = function (config, actionId, args) {\n var _this = this;\n return this.args.ruleService.runActionRuleByIdAsync(config, actionId, args || this.args.getRuleArgs(config))\n .then(function (res) {\n _this.handleRuleError(actionId, res);\n return res;\n });\n };\n ConfiguratorHelper.prototype.runOptionFilterSourceRule = function () {\n };\n ConfiguratorHelper.prototype.autoCompleteQuery = function (query, field) {\n if (query) {\n if (field.autoCompleteSource == enums.eAutoCompleteSource.table) {\n // return this.tablesPromise.then(() => {\n var arr = this.tableArraysDb[field.idTable].data;\n var results = _tools.SearchUtils.search(query, arr, function (item) { return item[_tools.Utils.scrubName(field.labelColumn || field.valueColumn)]; });\n var scrubValueCol_1 = _tools.Utils.scrubName(field.valueColumn);\n var scrubLabelCol_1 = _tools.Utils.scrubName(field.labelColumn);\n var scrubImageCol_1 = _tools.Utils.scrubName(field.imageColumn);\n // map the results to options\n var options = results.map(function (item) {\n var o = new enums.Option();\n o.value = item[scrubValueCol_1];\n o.label = item[scrubLabelCol_1];\n o.image = item[scrubImageCol_1];\n return o;\n });\n return this.args.$q.when(options);\n // });\n }\n else if (field.autoCompleteSource == enums.eAutoCompleteSource.database) {\n return this.args.api.products.autocomplete(field.$parentConfigurator.idProduct, field.id, query, this.args.tracker);\n }\n }\n return this.args.$q.when([]);\n };\n ConfiguratorHelper.prototype.autoCompleteGetLabel = function (value, field) {\n if (field.labelColumn) {\n // when autocomplete fields are using the labelColumn, then when they are first opening,\n // they will request for the label of their current value\n if (field.autoCompleteSource == enums.eAutoCompleteSource.table) {\n var scrubValueCol_2 = _tools.Utils.scrubName(field.valueColumn);\n var scrubLabelCol = _tools.Utils.scrubName(field.labelColumn);\n var scrubImageCol = _tools.Utils.scrubName(field.imageColumn);\n // return this.tablesPromise.then(() => {\n var arr = this.tableArraysDb[field.idTable].data;\n var row = arr.find(function (item) { return item[scrubValueCol_2] === value; });\n return row ? row[scrubLabelCol] : null;\n // });\n }\n else if (field.autoCompleteSource == enums.eAutoCompleteSource.database) ;\n }\n return value;\n };\n ConfiguratorHelper.prototype.getOptionFilterSource = function (filter) {\n var arr = [];\n if (filter.source == enums.eOptionFilterSource.table) {\n var tableObject = this.tableArraysDb[filter.idTable];\n if (tableObject)\n arr = tableObject.data;\n }\n else if (filter.source == enums.eOptionFilterSource.optionFilter) {\n var f = filter.$parentConfigurator.$manager.get(filter.idOptionFilter);\n arr = f ? f.$source : [];\n }\n else { //must be a query\n // get the source table by running the query\n var ruleArgs = this.args.getRuleArgs(filter.$parentConfigurator);\n arr = this.runRuleContainerSync(filter, ruleArgs).parameters.source;\n }\n if (arr == null)\n throw new Error(\"Could not find source for option filter '\".concat(filter.name, \"'\"));\n filter.$source = arr;\n return arr;\n };\n ConfiguratorHelper.prototype.shouldRunOptionFilter = function (config, filter) {\n var shouldRun = true;\n if (config.v >= 1 && filter.optimized) { // older configurators will not have the needed info for optimization\n var last_1 = filter.$lastValues;\n if (last_1) { // if it has lastReferenceValues then it has already been run\n shouldRun = Object.keys(last_1).some(function (fieldId) {\n var field = config.$manager.get(fieldId);\n if (field.isArrayType()) {\n return !field.value.equals(last_1[fieldId]);\n }\n else {\n return (last_1[fieldId] != field.value);\n }\n });\n }\n }\n // if this filter is sourced from another option filter, we need to also check if that option filter\n // needed to be run in this cycle\n if (filter.source == enums.eOptionFilterSource.optionFilter ||\n (filter.source == enums.eOptionFilterSource.query && filter.queryMode == enums.eQueryMode.optionFilter)) {\n var otherFilter = config.$manager.get(filter.idOptionFilter);\n shouldRun = otherFilter.$shouldRun || shouldRun;\n }\n else if (filter.source == enums.eOptionFilterSource.query && filter.queryMode == enums.eQueryMode.parentOptionFilter) {\n var otherFilter = config.$parentConfigurator.$manager.get(filter.idOptionFilter);\n shouldRun = otherFilter.$shouldRun || shouldRun;\n }\n filter.$shouldRun = shouldRun;\n return shouldRun;\n };\n ConfiguratorHelper.prototype.runOptionFilter = function (config, s) {\n var filter = config.$manager.get(s.filterId);\n // optimize by not running if all the inputs are the same as last time it was run\n var shouldRun = this.shouldRunOptionFilter(config, filter);\n if (shouldRun) {\n this._optionFilterRunCount++;\n var source_1 = this.getOptionFilterSource(filter);\n var clientLang = this.args.$rootScope.clientLanguage;\n var shouldTranslate = (clientLang != this.args.$rootScope.companySettings.defaultLanguage);\n // start with full table. //Use int array and preallocate it for performance reasons\n var matchedRows = [];\n for (var r = 0; r < source_1.length; r++) {\n matchedRows.push(r);\n }\n var _loop_1 = function (f) {\n // get the real field from this configurator\n var field = config.$manager.get(s.fieldIds[f]);\n var fieldBaseType = field.getBaseType();\n var fieldIsArray = field.isArrayType();\n var newOptions = [];\n var scrubValueCol = _tools.Utils.scrubName(field.valueColumn);\n var scrubLabelCol = _tools.Utils.scrubName(field.labelColumn);\n var scrubSortCol = _tools.Utils.scrubName(field.sortColumn);\n var scrubTranslateCol = shouldTranslate ?\n (scrubLabelCol ?\n scrubLabelCol + clientLang.toUpperCase()\n : scrubValueCol + clientLang.toUpperCase())\n : \"\";\n var scrubImageCol = _tools.Utils.scrubName(field.imageColumn);\n var scrubImageWhenSelectedCol = _tools.Utils.scrubName(field.imageWhenSelectedColumn);\n var scrubDescCol = _tools.Utils.scrubName(field.descriptionColumn);\n scrubDescTranslateCol = shouldTranslate ? (scrubDescCol + clientLang.toUpperCase()) : \"\";\n // fill in options... we only want unique options\n var uniqueDb = {};\n for (var _i = 0, matchedRows_1 = matchedRows; _i < matchedRows_1.length; _i++) {\n var rowIndex = matchedRows_1[_i];\n var row = source_1[rowIndex];\n if (!uniqueDb[row[scrubValueCol]]) {\n var entry = {\n label: row.hasOwnProperty(scrubTranslateCol) ? row[scrubTranslateCol] : row[scrubLabelCol],\n image: row[scrubImageCol],\n imageWhenSelected: row[scrubImageWhenSelectedCol],\n description: row.hasOwnProperty(scrubDescTranslateCol) ? row[scrubDescTranslateCol] : row[scrubDescCol],\n value: enums.Field.convertToType(row[scrubValueCol], fieldBaseType, field.precision),\n sort: row[scrubSortCol]\n };\n uniqueDb[row[scrubValueCol]] = entry;\n newOptions.push(entry);\n }\n }\n // sort if applicable\n var sortCol = field.sortColumn ? \"sort\" : (field.labelColumn ? \"label\" : \"value\");\n if (field.sort == enums.eSort.ascending) {\n newOptions.sortBy(function (o) { return o[sortCol]; });\n }\n else if (field.sort == enums.eSort.descending) {\n newOptions.sortByDescending(function (o) { return o[sortCol]; });\n }\n // set the new options all at once\n field.options = newOptions;\n this_1.handleSingleOption(field, filter);\n // now recalculate the matched rows for the next field\n if (f !== s.fieldIds.length - 1) {\n matchedRows = matchedRows.filter(function (rowIndex) {\n var cellValue = source_1[rowIndex][scrubValueCol];\n cellValue = enums.Field.convertToType(cellValue, fieldBaseType, field.precision);\n return fieldIsArray ? field.value.contains(cellValue) : (cellValue == field.value);\n });\n }\n };\n var this_1 = this, scrubDescTranslateCol;\n for (var f = 0; f < s.fieldIds.length; f++) {\n _loop_1(f);\n }\n this.storeLastValuesFor(config, s);\n }\n };\n ConfiguratorHelper.prototype.handleSingleOption = function (field, optionFilter) {\n // if there is only one option left, check the specified behavior on the option filter\n if (optionFilter.singleOptionBehavior == enums.eSingleOptionBehavior.disable) {\n field.enabled = (field.options.length > 1);\n }\n else if (optionFilter.singleOptionBehavior == enums.eSingleOptionBehavior.hide) {\n field.visible = (field.options.length > 1);\n }\n };\n ConfiguratorHelper.prototype.storeLastValuesFor = function (config, s) {\n if (config.v >= 1) { // older configurators will not have the needed info for optimization\n // store last field values for optimization\n var filter = config.$manager.get(s.filterId);\n var last_2 = filter.$lastValues = filter.$lastValues || {};\n filter.fieldReferences.forEach(function (fieldId) {\n var field = config.$manager.get(fieldId);\n if (field.isArrayType()) {\n last_2[fieldId] = field.value.map(function (v) { return v; });\n }\n else {\n last_2[fieldId] = field.value;\n }\n });\n s.fieldIds.forEach(function (fieldId) {\n var field = config.$manager.get(fieldId);\n if (field.isArrayType()) {\n last_2[field.id] = field.value.map(function (v) { return v; });\n }\n else {\n last_2[field.id] = field.value;\n }\n });\n }\n };\n ConfiguratorHelper.prototype.runSelects = function (config) {\n var _this = this;\n var promise = (new _rules.KPromise(null));\n if (!config.optionFilters.length)\n return promise; //shortcircuit if there is nothing to do here\n config.$freezeFieldValueCalculation = true; // freeze field value calculation for perf\n var startTime = Date.now();\n this._optionFilterRunCount = 0;\n // fill in the db\n if (!this.odb)\n this.odb = {};\n if (!this.odb[config.idProduct]) {\n this.odb[config.idProduct] = {};\n this.filterLevelDb[config.idProduct] = {};\n // loop through each select table, find all registered fields\n var allFields_1 = config.getFields(function (f) { return f.canJoinOptionFilter() && f.selectSource == enums.eSelectSource.optionFilter; });\n config.optionFilters.forEach(function (o) {\n var info = {\n filterId: o.id,\n fieldIds: allFields_1.filter(function (f) { return f.idOptionFilter == o.id; }).map(function (f) { return f.id; })\n };\n _this.odb[config.idProduct][o.id] = info;\n });\n // filters are organized by level of dependencies. Those at a level of 1 have no dependencies\n // so we just roll through the filters, and make a jagged array where the primary index is \n // the level, and we loop them and run them\n config.optionFilters.forEach(function (filter) {\n var arr = _this.filterLevelDb[config.idProduct][filter.level];\n if (!arr)\n _this.filterLevelDb[config.idProduct][filter.level] = [];\n _this.filterLevelDb[config.idProduct][filter.level].push(filter.id);\n });\n //// fill in start filters also\n // this.startFilters = config.optionFilters.filter(f => !f.dependsOn || f.dependsOn.length == 0);\n }\n // if any of the option filters in the configurator are sourced by a database, then we just have the server\n // do all the figuring\n if (!config.filtersShouldRunOnClient()) {\n /* another level of optimization... if all the fields referenced by option filters in their query\n rule and fields in the option filter haven't changed value, then there is no reason to call the server */\n var shouldRun = true;\n if (config.v >= 1) { // older configurators will not have the needed info for optimization\n for (var _i = 0, _a = config.optionFilters; _i < _a.length; _i++) {\n var filter = _a[_i];\n shouldRun = this.shouldRunOptionFilter(config, filter);\n if (shouldRun)\n break;\n }\n }\n if (shouldRun) {\n var fieldOptions_1 = [];\n config.optionFilters.forEach(function (filter) {\n _this.odb[config.idProduct][filter.id].fieldIds.forEach(function (fieldId) {\n var field = config.$manager.get(fieldId);\n fieldOptions_1.push({ id: field.id, name: field.name, options: field.options });\n });\n });\n var lastValues_1 = {};\n config.optionFilters.forEach(function (filter) {\n lastValues_1[filter.id] = filter.$lastValues;\n });\n var runArgs = {\n configuredProduct: config.getConfiguredProduct(true),\n lastValues: lastValues_1,\n fieldOptions: fieldOptions_1\n };\n promise = this.args.api.optionFilters.run(runArgs, this.args.tracker).then(function (r) {\n r.filters.forEach(function (filterResult) {\n filterResult.fields.forEach(function (f) {\n var field = config.$manager.get(f.id);\n var filter = config.$manager.get(filterResult.id);\n // sort if applicable\n var sortCol = field.sortColumn ? \"sort\" : (field.labelColumn ? \"label\" : \"value\");\n if (field.sort == enums.eSort.ascending) {\n f.options.sortBy(function (o) { return o[sortCol]; });\n }\n else if (field.sort == enums.eSort.descending) {\n f.options.sortByDescending(function (o) { return o[sortCol]; });\n }\n field.options = f.options;\n _this.handleSingleOption(field, filter);\n });\n });\n // store optimization info\n r.filters.forEach(function (filter) { return _this.storeLastValuesFor(config, _this.odb[config.idProduct][filter.id]); });\n });\n }\n }\n else {\n /* we have all tables, and no databases, so we operate locally to avoid a roundtrip to the server\n because getTables is a KPromise that isn't a real promise, we can run these as if they were\n sync (because they are) */\n var level = 1;\n while (true) {\n var filterIds = this.filterLevelDb[config.idProduct][level];\n if (filterIds) {\n filterIds.forEach(function (filterId) {\n _this.runOptionFilter(config, _this.odb[config.idProduct][filterId]);\n });\n level++;\n }\n else {\n break;\n }\n }\n promise = (new _rules.KPromise(null)).then(function () {\n // store optimization info\n config.optionFilters.forEach(function (filter) { return _this.storeLastValuesFor(config, _this.odb[config.idProduct][filter.id]); });\n });\n }\n return promise.then(function () {\n config.$freezeFieldValueCalculation = false;\n _tools.Logger.logRuleEnd(config.name, \"option filters (\".concat(_this._optionFilterRunCount, \")\"), startTime);\n });\n };\n return ConfiguratorHelper;\n }());\n\n var SCENE_CLICK_HANDLER_TAG = 'scene_click';\n var Kb3dViewer = /** @class */ (function (_super) {\n __extends(Kb3dViewer, _super);\n function Kb3dViewer(cArgs) {\n var _this = _super.call(this, cArgs) || this;\n _this.cArgs = cArgs;\n _this.hotspotCounter = 0;\n _this.enableScreenshots = cArgs.enableScreenshots || false;\n //this.sceneService = args.$injector.get(Token.ClaraSceneService.key);\n //this.$scope = cArgs.controllerScope.$new();\n _this.$scope.hotspotClick = function ($event, ann) { return _this.hotspotClick($event, ann); };\n _this.$scope.hotspotCloseClick = function ($event, ann) { return _this.hotspotCloseClick($event, ann); };\n _this.$scope.arActive = function () { return _this.viewer.ar.xrActive; };\n _this.$scope.toggleAr = function () { return _this.toggleAr(); };\n _this.$scope.arEnabled = true;\n _tools.Utils.supportsVr().then(function (res) { return (_this.$scope.supportsVr = res); });\n _this.$scope.allHotspots = [];\n return _this;\n }\n Kb3dViewer.prototype.init = function () {\n var _this = this;\n this.createElem();\n this.viewer = new kb3d.KbViewer({\n container: this.elem,\n highlightColor: this.highlightColor ? kb3d.KbColor.FromIntObject(new _tools.Color(this.highlightColor).toRgb()) : null,\n webworkerPath: this.clusterEnv === 'dev'\n ? \"\".concat(this.assetRoot, \"/worker3d.js\")\n : \"\".concat(this.assetRoot, \"/worker3d.min.js?v=\").concat(this.cacheBuster),\n debugMode: this.clusterEnv === 'dev',\n forceDisableGraphicsOptimization: this.isRender,\n enableScreenshots: this.enableScreenshots,\n });\n this.elem.addEventListener('kb3d.scenePropertyChange', function (e) {\n if ('arEnabled' in e.detail) {\n var arEnabled_1 = e.detail['arEnabled'];\n _this.$scope.$apply(function () {\n _this.$scope.arEnabled = arEnabled_1;\n });\n }\n });\n this.createHotspotElem();\n this.viewer.viewChanged.subscribe(function () { return _this.updateHotspots(true); });\n this.viewer.interaction.onKeyboard.subscribe(function (k) { return _this.onKeyboard(k); });\n return new _rules.KPromise(null);\n };\n Kb3dViewer.prototype.dispose = function () {\n if (this.viewer) {\n this.viewer.gizmos.clearGizmo();\n this.viewer.dispose();\n }\n if (this.sceneNode && this.sceneNode._manager) {\n this.sceneNode._manager.clickHandlers.deleteByTag(SCENE_CLICK_HANDLER_TAG);\n }\n if (this.elem) {\n this.elem.remove();\n this.elem = null;\n }\n };\n Kb3dViewer.prototype.loadSceneInternal = function (args) {\n var _this = this;\n var manager = new kb3d.Kb3dManager({\n assetRoot: this.assetRoot,\n forceFullSizeTextures: args.isRenderContext || false,\n environment: {\n lastDeploy: this.lastDeploy,\n cacheBuster: this.cacheBuster,\n },\n }); //default services automatically used\n this.sceneNode = manager.deserialize(this.scene.graph);\n this.$scope.arEnabled = !!this.sceneNode.arEnabled;\n this.$scope.fullscreenEnabled = !!this.sceneNode.fullscreenEnabled;\n args.config.$sceneNode = this.sceneNode;\n this.sceneNode._configurator = args.config;\n //args.loadingExperience is set to false in render.ts to disable loading experiences for renders\n if (args.loadingExperience === false) {\n this.viewer.loadScene({\n sceneNode: this.sceneNode,\n loadingExperience: kb3d.eLoadingExperience.none,\n deferLoadingPromise: this.$q.all([this.loadDeferred.promise, this.configuratorLoadedPromise]),\n });\n }\n else {\n this.viewer.loadScene({\n sceneNode: this.sceneNode,\n deferLoadingPromise: this.$q.all([this.loadDeferred.promise, this.configuratorLoadedPromise]),\n });\n }\n manager.clickHandlers.add(this.sceneNode, SCENE_CLICK_HANDLER_TAG, function (p) {\n _this.onSceneClick(p);\n });\n return this.runRules(false).then(function () {\n _this.notifyLoaded();\n });\n };\n Kb3dViewer.prototype.runRules = function (waitForLoad) {\n var _this = this;\n if (waitForLoad === void 0) { waitForLoad = true; }\n var promise = waitForLoad ? this.loadDeferred.promise : new _rules.KPromise(null);\n return promise\n .then(function () {\n var ruleArgs = _this.getRuleArgs(enums.eRuleType.scene);\n _this.setFieldsIfStandalone();\n // before running the value rules, we need to clear out transient handlers\n _this.clearTransientHandlers(_this.sceneNode, enums.eRuleType.value);\n var runUiRules = !_this.sceneDb[_this.sceneConfig.idScene].idProduct;\n if (runUiRules) {\n // run the value rule first\n // ruleArgs.sceneUtils.ruleType = eRuleType.value;\n return _this.runRuleTypeAsync(_this.sceneConfig, enums.eRuleType.value, _this.getRuleArgs(enums.eRuleType.value)).then(function () {\n _this.sceneConfig.preValidate();\n _this.sceneConfig.isValid();\n });\n }\n })\n .then(function () {\n return _this.runSceneRules(_this.sceneConfig, _this.uiConfig, _this.getRuleArgs(enums.eRuleType.scene), false);\n })\n .then(function (result) {\n _this.handleRuleError(enums.eRuleType.scene, result);\n //recalculate all hotspots\n _this.$scope.allHotspots = _this.getAllHotspots();\n _this.updateHotspots(false);\n return result;\n });\n };\n Kb3dViewer.prototype.clearTransientHandlers = function (sceneNode) {\n var ruleTypes = [];\n for (var _i = 1; _i < arguments.length; _i++) {\n ruleTypes[_i - 1] = arguments[_i];\n }\n var m = sceneNode._manager;\n var handlerMaps = [m.clickHandlers, m.doubleClickHandlers, m.draggables, m.hotspotClickHandlers];\n for (var _a = 0, handlerMaps_1 = handlerMaps; _a < handlerMaps_1.length; _a++) {\n var hm = handlerMaps_1[_a];\n hm.deleteByTag.apply(hm, ruleTypes);\n }\n };\n Kb3dViewer.prototype.runSceneRules = function (sceneConfig, uiConfig, ruleArgs, skipRulesIfNoNestedSceneChanges) {\n var _this = this;\n var nestedSceneRulesWereRun = false;\n return this.runNestedSceneRules(uiConfig)\n .then(function (r) {\n nestedSceneRulesWereRun = r && r.some(function (r2) { return r2 != null; });\n if (!sceneConfig.$ranLoadedRule) {\n sceneConfig.$ranLoadedRule = true;\n skipRulesIfNoNestedSceneChanges = false;\n ruleArgs.ruleType = enums.eRuleType.sceneLoaded;\n return _this.runRuleTypeAsync(sceneConfig, enums.eRuleType.sceneLoaded, ruleArgs);\n }\n })\n .then(function () {\n _this.deleteOrphanedNestedScenes(uiConfig);\n if (!skipRulesIfNoNestedSceneChanges || nestedSceneRulesWereRun) {\n //skip running the rules if there were no nested scene rules run\n _this.clearTransientHandlers(ruleArgs.sceneNode, enums.eRuleType.scene);\n ruleArgs.ruleType = enums.eRuleType.scene;\n return _this.runRuleTypeAsync(sceneConfig, enums.eRuleType.scene, ruleArgs).then(function (ruleResult) {\n uiConfig.$fieldsDirtyForSceneRules = false;\n return ruleResult;\n });\n }\n });\n };\n Kb3dViewer.prototype.runNestedSceneRules = function (uiConfig) {\n var _this = this;\n var nestedConfigs = uiConfig.getNestedConfigurators();\n if (nestedConfigs.length) {\n var promises_1 = [];\n // loop through nested configurators, merge the scenes if they haven't been already, and run their rules\n nestedConfigs.forEach(function (nested) {\n if (nested.idScene) {\n var refConfig = uiConfig.referencedConfigurators.find(function (rc) { return rc.idProduct == nested.idProduct; });\n if (refConfig.nestScene) {\n // create the scene configurator for the nested configurator if it doesn't already exist\n // (or has been swapped for another scene)\n if (!nested.$sceneConfigurator || nested.$sceneConfigurator.idScene != nested.idScene) {\n nested.$sceneConfigurator = new enums.Configurator(new enums.KbObjectManager(), _this.sceneDb[nested.idScene].configurator);\n }\n nested.$sceneConfigurator.$uiConfigurator = nested;\n nested.$nestHotspots = refConfig.nestHotspots;\n // in case the nested scene is a standalone scene, we need to set it's fields from the uiConfig\n nested.$sceneConfigurator.setFields(nested.getFieldsObject());\n var skipRules = !nested.$fieldsDirtyForSceneRules && (!nested.alwaysChild || !nested.alwaysChildOf);\n _this.nestScene(\n // merge the scene if it hasn't already been merged\n uiConfig.$sceneNode, nested);\n promises_1.push(\n // now run the rules on the nested scene\n _this.runSceneRules(nested.$sceneConfigurator, nested, _this.getNestedSceneRuleArgs(nested, nested.$sceneConfigurator, enums.eRuleType.scene), skipRules));\n }\n }\n });\n return this.$q.all(promises_1);\n }\n else {\n return new _rules.KPromise(null);\n }\n };\n Kb3dViewer.prototype.nestScene = function (parentSceneNode, nested) {\n var _this = this;\n if (!nested.$sceneNode) {\n //nested scene has already been created so skip\n var ser = this.sceneDb[nested.idScene];\n var nestedSceneNode = parentSceneNode._manager.nestScene(nested.name, parentSceneNode, ser.graph);\n nested.$sceneNode = nestedSceneNode;\n nestedSceneNode._configurator = nested;\n //add automatic click to navigate if enabled\n if (nested.$parentConfigurator.nestedSceneClickToSelect) {\n parentSceneNode._manager.clickHandlers.add(nestedSceneNode, undefined, function () {\n _this.navigateToElement(nested);\n });\n }\n }\n };\n Kb3dViewer.prototype.runRuleTypeAsync = function (config, ruleType, args) {\n var _this = this;\n return this.ruleService.runRuleTypeAsync(config, ruleType, args).then(function (res) {\n _this.handleRuleError(ruleType, res);\n return res;\n });\n };\n Kb3dViewer.prototype.deleteOrphanedNestedScenes = function (uiConfig) {\n var allNested = uiConfig.getNestedConfigurators();\n var sceneNode = uiConfig.$sceneNode;\n if (sceneNode) {\n for (var i = sceneNode.scenes.length - 1; i >= 0; i--) {\n var ns = sceneNode.scenes[i];\n if (!allNested.some(function (n) { return n === ns._configurator; })) {\n this.destroyNestedScene(sceneNode, ns);\n }\n }\n }\n };\n Kb3dViewer.prototype.destroyNestedScene = function (parentScene, nestedScene) {\n var nestedConfig = nestedScene._configurator;\n if (nestedConfig)\n nestedConfig.$sceneNode = undefined;\n nestedScene._configurator = undefined;\n parentScene.scenes.remove(nestedScene);\n nestedScene._manager.dispose(); //dispose of the nested scene manager\n };\n Kb3dViewer.prototype.clearHandlers = function () { };\n Kb3dViewer.prototype.runAction = function (actionName) {\n var args = this.getRuleArgs(enums.eRuleType.action);\n return this.runActionRule(actionName, args);\n };\n Kb3dViewer.prototype.runSceneFunction = function (args, config) {\n var _this = this;\n var ruleArgs = null;\n if (config && config.$sceneConfigurator) {\n ruleArgs = this.getNestedSceneRuleArgs(config, config.$sceneConfigurator, enums.eRuleType.function);\n }\n else {\n ruleArgs = this.getRuleArgs(enums.eRuleType.function);\n }\n ruleArgs.parameters = {};\n for (var p in args.parameters) {\n ruleArgs.parameters[p.toCamelCase()] = args.parameters[p];\n }\n var fn = null;\n if (config && config.$sceneConfigurator) {\n fn = config.$sceneConfigurator.functions.find(function (a) { return a.name.isEqual(args.name); });\n }\n if (!fn) {\n fn = this.sceneConfig.functions.find(function (a) { return a.name.isEqual(args.name); });\n }\n if (fn) {\n return this.ruleService.runRuleContainerAsync(fn, ruleArgs).then(function (r) {\n _this.handleRuleError(fn.name + ' ' + fn.$type, r);\n return r;\n });\n }\n else {\n throw \"Cannot find scene function with name \".concat(args.name);\n }\n };\n Kb3dViewer.prototype.runFieldAction = function (elem) {\n var _this = this;\n var args = this.getRuleArgs(enums.eRuleType.field);\n return this.ruleService.runRuleContainerAsync(elem, args).then(function (res) {\n _this.handleRuleError(elem.name + ' ' + elem.$type, res);\n return res;\n });\n };\n Kb3dViewer.prototype.onSceneClick = function (p) {\n this.clearHotspots();\n this.$scope.$digest();\n };\n Kb3dViewer.prototype.onKeyboard = function (k) {\n var _this = this;\n var args = this.getRuleArgs(enums.eRuleType.action);\n args['keyArgs'] = k;\n return this.ruleService\n .runRuleTypeAsync(this.sceneConfig, enums.eRuleType.keyboard, args)\n .then(function (r) {\n _this.handleRuleError(enums.eRuleType.keyboard, r);\n _this.$scope.$digest();\n });\n };\n Kb3dViewer.prototype.importUploadFieldImage = function (uiConfig, field, file) {\n return undefined;\n };\n Kb3dViewer.prototype.show = function () {\n _super.prototype.show.call(this);\n this.viewer.startRender();\n };\n Kb3dViewer.prototype.hide = function () {\n this.viewer.stopRender();\n _super.prototype.hide.call(this);\n };\n Kb3dViewer.prototype.resize = function () { };\n Kb3dViewer.prototype.snapshot = function (args) {\n if (args['camera'] && !args.viewpoint)\n args.viewpoint = args['camera']; //backwards compatibility for old snapshot\n return this.viewer.snapshot.take(args);\n };\n Kb3dViewer.prototype.toggleAr = function () {\n var _this = this;\n var rulesFn = function (rt) {\n return _this.runRuleTypeAsync(_this.sceneConfig, rt, _this.getRuleArgs(rt)).then(function () {\n return _this.runRules(false);\n });\n };\n if (this.arLoading.active()) {\n return;\n }\n var ruleType = this.$scope.arActive() ? enums.eRuleType.xrExit : enums.eRuleType.xrEnter;\n if (ruleType == enums.eRuleType.xrEnter) {\n var subscription_1 = this.viewer.ar.onSessionEnd.subscribe(function () {\n subscription_1.unsubscribe();\n return rulesFn(enums.eRuleType.xrExit);\n });\n var overlayElem = document.querySelector('.xr-overlay');\n var arPromise = this.viewer.ar\n .start(overlayElem, function () { return rulesFn(enums.eRuleType.xrEnter); })\n .catch(function (err) {\n if (_this.cArgs.dialogService) {\n _this.$scope.$apply(function () {\n _this.cArgs.dialogService.alert({\n type: enums.eAlertType.error,\n msg: 'Could not enter AR: ' + err,\n persist: true,\n });\n });\n }\n else {\n console.warn('No Dialog Service!');\n console.error(err);\n }\n });\n this.arLoading.addPromise(arPromise);\n return arPromise;\n }\n else {\n return this.viewer.ar.end();\n }\n };\n Kb3dViewer.prototype.updateHotspots = function (digest) {\n var _this = this;\n var _a, _b;\n if (digest === void 0) { digest = true; }\n var hotspotProcessed = false;\n var _loop_1 = function (hotspot) {\n var sceneNode = (_b = (_a = hotspot.$parentConfigurator) === null || _a === void 0 ? void 0 : _a.$uiConfigurator) === null || _b === void 0 ? void 0 : _b.$sceneNode;\n if (sceneNode) {\n var sceneManager = sceneNode._manager;\n if (sceneManager) {\n if (hotspot.target && hotspot.targetNode && hotspot.visible) {\n hotspotProcessed = true;\n var targetNode = sceneManager.getById(hotspot.targetNode);\n if (targetNode) {\n var pos = this_1.viewer.camera.getScreenBoundingBoxOfNode(targetNode);\n if (pos) {\n this_1.positionHotspot(pos, hotspot);\n }\n }\n }\n if (hotspot.targetShape == enums.eHotspotShape.mesh && hotspot.targetNode) {\n var eventTag = \"hotspot_\".concat(hotspot.id);\n var node = sceneManager.getById(hotspot.targetNode);\n if (node) {\n if (hotspot.visible) {\n if (!sceneManager.clickHandlers.has(node, eventTag)) {\n sceneManager.clickHandlers.add(node, eventTag, function () {\n return _this.hotspotClick({}, hotspot);\n });\n }\n }\n else {\n //remove the click handler if the hotspot is invisible\n sceneManager.clickHandlers.delete(node, eventTag);\n }\n }\n }\n }\n }\n };\n var this_1 = this;\n for (var _i = 0, _c = this.$scope.allHotspots; _i < _c.length; _i++) {\n var hotspot = _c[_i];\n _loop_1(hotspot);\n }\n // call digest manually on this scope instead of scope.$apply because $apply starts\n // at the root and digests everything.We only want to affect the hotspots here.\n if (hotspotProcessed && digest) {\n //this can be expensive, so only run if there is something to update\n this.$scope.$digest();\n }\n };\n Kb3dViewer.prototype.clearHotspots = function () {\n for (var _i = 0, _a = this.$scope.allHotspots; _i < _a.length; _i++) {\n var hotspot = _a[_i];\n if (hotspot.target && hotspot.allowClose) {\n hotspot.open = false;\n }\n }\n };\n Kb3dViewer.prototype.hotspotClick = function ($event, hotspot) {\n var _this = this;\n this.clearHotspots();\n hotspot.open = true;\n this.hotspotCounter++;\n hotspot.$zindex = this.hotspotCounter;\n var hSceneNode = hotspot.$parentConfigurator.$uiConfigurator.$sceneNode;\n var handlers = hSceneNode._manager.hotspotClickHandlers.getByKey(hotspot);\n if (hotspot.idCamera) {\n var viewpoint = hSceneNode._manager.getById(hotspot.idCamera);\n if (viewpoint) {\n this.viewer.camera.animateToViewpoint(viewpoint, {\n duration: hotspot.animationDuration,\n });\n }\n }\n for (var _i = 0, handlers_1 = handlers; _i < handlers_1.length; _i++) {\n var handler = handlers_1[_i];\n var clickArgs = { propagate: false };\n handler(clickArgs);\n }\n // some hotspot popups start off the screen because the height can't be calculated until it's shown\n // so we need to offload to recalculate the hotspot position after the digest\n this.$timeout(function () {\n if (hotspot.target && hotspot.targetNode && hotspot.visible) {\n var targetNode = hSceneNode._manager.getById(hotspot.targetNode);\n if (targetNode) {\n var pos = _this.viewer.camera.getScreenBoundingBoxOfNode(targetNode);\n if (pos) {\n _this.positionHotspot(pos, hotspot);\n }\n }\n }\n });\n };\n Kb3dViewer.prototype.hotspotCloseClick = function ($event, hotspot) {\n $event.stopPropagation();\n hotspot.open = false;\n };\n Kb3dViewer.prototype.getRuleArgs = function (ruleType) {\n var args;\n if (ruleType == enums.eRuleType.function) {\n args = new Kb3dSceneFunctionRuleArgs(this);\n }\n else {\n args = new Kb3dSceneRuleArgs(this);\n }\n args.environment = this.environment;\n args.baseUrl = this.baseUrl;\n args.configurator = this.sceneConfig.idProduct ? this.uiConfig : this.sceneConfig;\n args.kom = args.configurator.$manager;\n args.parentKom = args.configurator.$parentConfigurator ? args.configurator.$parentConfigurator.$manager : null;\n args.sceneKom = this.sceneConfig.$manager;\n args.sceneNode = this.sceneNode;\n //args.sceneApi = this.sceneApi;\n args.isRender = this.isRender;\n args.renderPass = this.renderPass;\n //args.sceneUtils = this.sceneService.getSceneUtilities(this.sceneApi, ruleType);\n args.clientLanguage = this.clientLanguage;\n args.ruleType = ruleType;\n args.xrActive = this.viewer.ar.xrActive;\n return args;\n };\n Kb3dViewer.prototype.getNestedSceneRuleArgs = function (uiConfig, sceneConfig, ruleType) {\n var args = new Kb3dSceneRuleArgs(this);\n args.environment = this.environment;\n args.baseUrl = this.baseUrl;\n args.configurator = uiConfig;\n args.kom = args.configurator.$manager;\n args.parentKom = args.configurator.$parentConfigurator ? args.configurator.$parentConfigurator.$manager : null;\n args.sceneKom = sceneConfig.$manager;\n args.sceneNode = uiConfig.$sceneNode;\n //args.sceneApi = this.sceneApi;\n args.isRender = this.isRender;\n args.renderPass = this.renderPass;\n //args.sceneUtils = this.sceneService.getSceneUtilities(this.sceneApi, ruleType);\n args.clientLanguage = this.clientLanguage;\n args.ruleType = ruleType;\n args.xrActive = this.viewer.ar.xrActive;\n return args;\n };\n return Kb3dViewer;\n }(SceneViewer));\n var Kb3dSceneRuleArgs = /** @class */ (function () {\n function Kb3dSceneRuleArgs(kbv) {\n this.kbv = kbv;\n this.logs = new _rules.ClientLogger();\n this.isMobile = kbv.isMobile;\n }\n Kb3dSceneRuleArgs.prototype.upload = function () {\n //return this.viewer.upload();\n };\n Kb3dSceneRuleArgs.prototype.sendMessage = function (msg) {\n this.kbv.sendMessage(msg);\n };\n Kb3dSceneRuleArgs.prototype.selectPage = function (page) {\n if (this.kbv.navigateToElement) {\n this.kbv.navigateToElement(page);\n }\n };\n Kb3dSceneRuleArgs.prototype.convertCurrency = function (obj) {\n return null;\n };\n Kb3dSceneRuleArgs.prototype.getTables = function (args) {\n var _this = this;\n return new _rules.KPromise(args.ids.map(function (tid) { return _this.kbv.tableArraysDb[tid]; }));\n };\n Kb3dSceneRuleArgs.prototype.getById = function (id) {\n return this.sceneNode._manager.getById(id);\n };\n Kb3dSceneRuleArgs.prototype.getByName = function (name) {\n var node = this.sceneNode._manager.getFirstNodeByName(name, true);\n if (!node) {\n console.warn(\"No nodes \\\"\".concat(name, \"\\\" found\"));\n }\n };\n Kb3dSceneRuleArgs.prototype.getIdByName = function (name) {\n var node = this.sceneNode._manager.getNodeByIdOrName(name);\n if (!node) {\n console.warn(\"No nodes \\\"\".concat(name, \"\\\" found\"));\n }\n else {\n return node.id;\n }\n };\n Kb3dSceneRuleArgs.prototype.getParent = function (n) {\n var node = this.sceneNode._manager.getNodeByIdOrName(n);\n if (node) {\n return node._parent;\n }\n };\n Kb3dSceneRuleArgs.prototype.getNestedPathTo = function (node) {\n return this.sceneNode.getNestedPathTo(node);\n };\n Kb3dSceneRuleArgs.prototype.getNestedPathInConfigurator = function () {\n var _this = this;\n var configs = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n configs[_i] = arguments[_i];\n }\n var m = this.sceneNode._manager;\n var lastItem = configs.pop(); // Last item can be a node ID or name as well\n var path = configs.reduce(function (result, config) {\n if (typeof config === 'string') {\n result += config;\n var configurator = _this.kom.getByName(config);\n if (configurator instanceof enums.Configurator && configurator.$sceneNode) {\n m = configurator.$sceneNode._manager;\n }\n }\n else {\n result += config.name;\n if (config.$sceneNode) {\n m = config.$sceneNode._manager;\n }\n }\n return result + '/';\n }, '');\n if (typeof lastItem === 'string') {\n var lastConfig = this.kom.getByName(lastItem, false);\n if (lastConfig instanceof enums.Configurator) {\n if (!lastConfig.$sceneNode) {\n console.warn('No Scene on configurator ' + lastConfig.name);\n return null;\n }\n path += lastConfig.name + '/' + lastConfig.$sceneNode.id;\n }\n else {\n var kb3dNode = m.getFirstNodeByName(lastItem);\n if (kb3dNode) {\n path += kb3dNode.id;\n }\n else {\n path += lastItem;\n }\n }\n }\n else {\n var lastConfig = lastItem;\n if (!lastConfig.$sceneNode) {\n console.warn('No Scene on configurator ' + lastConfig.name);\n return null;\n }\n path += lastConfig.name + '/' + lastConfig.$sceneNode.id;\n }\n return '@' + path;\n };\n Kb3dSceneRuleArgs.prototype.setParent = function (opts) {\n var manager = this.sceneNode._manager;\n var item = manager.getNodeByIdOrName(opts.node);\n var newParentNode = opts.newParent ? manager.getNodeByIdOrName(opts.newParent, false) : undefined;\n var transform = opts.preservePosition && kb3d.isSpaceNode(item)\n ? this.kbv.viewer.getTransformSpaceDifference(item, newParentNode)\n : undefined;\n var clickHandlers;\n var doubleClickHandlers;\n var draggables;\n if (item._parent) {\n if (kb3d.isSpaceNode(item) || kb3d.isAnnotation(item)) {\n clickHandlers = manager.clickHandlers.deleteByKey(item);\n doubleClickHandlers = manager.doubleClickHandlers.deleteByKey(item);\n draggables = manager.draggables.deleteByKey(item);\n }\n item._parent.removeChildren(item);\n }\n return this.kbv.viewer.forceAndWaitForNextRender().then(function () {\n if (transform && kb3d.isSpaceNode(item)) {\n item.setRotationQuaternion(transform.rotationQuaternion);\n item.scaling = transform.scale;\n item.position = transform.translation;\n }\n newParentNode.addChildren(item);\n item.calculateParents();\n if (kb3d.isSpaceNode(item) || kb3d.isAnnotation(item)) {\n if (clickHandlers) {\n for (var tag in clickHandlers) {\n for (var _i = 0, _a = clickHandlers[tag]; _i < _a.length; _i++) {\n var handler = _a[_i];\n manager.clickHandlers.add(item, tag, handler);\n }\n }\n }\n if (doubleClickHandlers) {\n for (var tag in doubleClickHandlers) {\n for (var _b = 0, _c = doubleClickHandlers[tag]; _b < _c.length; _b++) {\n var handler = _c[_b];\n manager.doubleClickHandlers.add(item, tag, handler);\n }\n }\n }\n if (draggables) {\n for (var tag in draggables) {\n for (var _d = 0, _e = draggables[tag]; _d < _e.length; _d++) {\n var handler = _e[_d];\n manager.draggables.add(item, tag, handler);\n }\n }\n }\n }\n });\n // const newNode = this.clone({ node: item, parent: newParentNode });\n };\n Kb3dSceneRuleArgs.prototype.setProperty = function (args) {\n var m = this.sceneNode._manager;\n var nodes = new Array();\n var id = args.id;\n if (args.nested) {\n nodes.push(this.getNestedSceneNode(args.nested));\n }\n else if (id && (id instanceof kb3d.Kb3dObject || id === this.kbv.viewer.camera.activeCamera)) {\n nodes.push(id);\n }\n else {\n nodes = m.getNodesByIdOrName(args.id, true);\n }\n if (nodes.length === 0) {\n console.warn(\"No nodes \\\"\".concat(args.id, \"\\\" found\"));\n }\n if (args.feature) {\n nodes = nodes.selectMany(function (n) {\n return n instanceof kb3d.MaterialNode\n ? n.getTextureByName(args.feature)\n : n instanceof kb3d.SpaceNode\n ? n.getFeatureByName(args.feature)\n : null;\n });\n }\n for (var _i = 0, nodes_1 = nodes; _i < nodes_1.length; _i++) {\n var node = nodes_1[_i];\n if (args.subProp && !kb3d.Token.withKey(args.propType).isPrimitive()) {\n //cover the case of TextureNodes inside a material\n node[args.prop][args.subProp] = args.value;\n }\n else {\n var val = this.normalizePropValue(node, args);\n node[args.prop] = val;\n }\n }\n };\n Kb3dSceneRuleArgs.prototype.getProperty = function (args) {\n var m = this.sceneNode._manager;\n var id = args.id;\n var node;\n if (id && (id instanceof kb3d.Kb3dObject || id === this.kbv.viewer.camera.activeCamera)) {\n node = id;\n }\n else {\n node = m.getNodeByIdOrName(args.id, true);\n }\n if (args.feature && node instanceof kb3d.MaterialNode) {\n node = node.getTextureByName(args.feature);\n }\n if (args.feature && node instanceof kb3d.SpaceNode) {\n node = node.getFeatureByName(args.feature);\n }\n if (node) {\n var val = args.prop ? node[args.prop] : node;\n if (args.prop && args.subProp)\n val = val[args.subProp];\n return val;\n }\n else {\n console.warn(\"No nodes \\\"\".concat(args.id, \"\\\" found\"));\n }\n };\n Kb3dSceneRuleArgs.prototype.normalizePropValue = function (node, args) {\n var _a;\n if (!args.subProp && args.value == null) {\n return null; // Return null as-is if applying directly to the prop\n }\n if (!args.subProp && args.propType && args.propType.isEqual(kb3d.Token.KbColor.key)) {\n return this.convertColor(args.value, enums.eColorFormat.kbcolor);\n }\n if (args.subProp) {\n if (kb3d.Token.withKey(args.propType).isPrimitive()) {\n if (args.value == null) {\n throw Error(\"Cannot set component of \".concat(args.propType, \" to null (on \").concat(node.name, \"/\").concat(args.prop, \")\"));\n }\n var currentVal = node[args.prop];\n var newVal = __assign(__assign({}, currentVal), (_a = {}, _a[args.subProp] = args.value, _a));\n return this.sceneNode._manager.create(kb3d.Token.withKey(args.propType), newVal);\n } /**else { //it's not a primitive but has a sub property\n node[args.prop][args.subProp] = args.value;\n return node[args.prop];\n }*/\n }\n return args.value;\n };\n Kb3dSceneRuleArgs.prototype.getNestedSceneNode = function (nestedNameOrInstance) {\n var nestedConfig;\n if (typeof nestedNameOrInstance === 'string' || nestedNameOrInstance instanceof String) {\n //if it's a string find the nested configurator\n nestedConfig = this.configurator.$manager.getByName(nestedNameOrInstance);\n }\n else if (nestedNameOrInstance instanceof enums.Configurator) {\n nestedConfig = nestedNameOrInstance;\n }\n if (!nestedConfig) {\n throw Error(\"could not find nested configurator with name '\".concat(nestedNameOrInstance, \"'\"));\n }\n return nestedConfig.$sceneNode;\n };\n Kb3dSceneRuleArgs.prototype.convertColor = function (from, toFormat) {\n if (toFormat === void 0) { toFormat = enums.eColorFormat.kbcolor; }\n if (toFormat == enums.eColorFormat.kbcolor && from instanceof kb3d.KbColor) {\n return from;\n }\n if (from instanceof kb3d.KbColor) {\n from = from.toIntObject();\n }\n var color = new _tools.Color(from);\n var result;\n if (toFormat == enums.eColorFormat.hex) {\n result = color.toHexString();\n }\n else if (toFormat == enums.eColorFormat.hsl) {\n result = color.toHsl();\n }\n else if (toFormat == enums.eColorFormat.hslString) {\n result = color.toHslString();\n }\n else if (toFormat == enums.eColorFormat.hsv) {\n result = color.toHsv();\n }\n else if (toFormat == enums.eColorFormat.hsvString) {\n result = color.toHsvString();\n }\n else if (toFormat == enums.eColorFormat.rgb) {\n result = color.toRgb();\n }\n else if (toFormat == enums.eColorFormat.rgbString) {\n result = color.toRgbString();\n }\n else if (toFormat == enums.eColorFormat.kbcolor) {\n var rgb = color.toRgb();\n result = kb3d.KbColor.FromIntObject(rgb);\n }\n return result;\n };\n Kb3dSceneRuleArgs.prototype.colorOperation = function (args) {\n if (args.color instanceof kb3d.KbColor) {\n args.color = args.color.toIntObject();\n }\n var color = new _tools.Color(args.color);\n color = color[args.operation](args.amount);\n return kb3d.KbColor.FromIntObject(color.toRgb());\n };\n Kb3dSceneRuleArgs.prototype.addClickHandler = function (args) {\n args.handler = this.digestEvent(args.handler); //the viewer runs the event, so we need to wrap it for the angular digest\n this.sceneNode._manager.clickHandlers.add(args.id, this.getHandlerTag(args.tag), args.handler);\n };\n Kb3dSceneRuleArgs.prototype.addDoubleClickHandler = function (args) {\n args.handler = this.digestEvent(args.handler); //the viewer runs the event, so we need to wrap it for the angular digest\n this.sceneNode._manager.doubleClickHandlers.add(args.id, this.getHandlerTag(args.tag), args.handler);\n };\n Kb3dSceneRuleArgs.prototype.addDraggable = function (args) {\n this.sceneNode._manager.draggables.add(args.id, this.getHandlerTag(args.tag), args);\n };\n Kb3dSceneRuleArgs.prototype.addHotspotClickHandler = function (args) {\n //no $digest wrap needed for hotspot handler because the event is already coming from angular\n this.sceneNode._manager.hotspotClickHandlers.set(args.hotspot, this.getHandlerTag(args.tag), args.handler);\n };\n Kb3dSceneRuleArgs.prototype.addBoundboxChangeHandler = function (args) {\n args.handler = this.digestEvent(args.handler); //the viewer runs the event, so we need to wrap it for the angular digest\n this.sceneNode._manager.boundingboxChangeHandlers.add(args.id, this.getHandlerTag(args.tag), {\n handler: args.handler,\n mode: args.mode,\n });\n };\n Kb3dSceneRuleArgs.prototype.getHandlerTag = function (argsTag) {\n if (this.ruleType == enums.eRuleType.scene) {\n //scene rule handlers get a tag of 'scene' automatically and are removed automatically\n return enums.eRuleType.scene;\n }\n else {\n //those added by other rules get the tag given by the snap user\n return argsTag;\n }\n };\n Kb3dSceneRuleArgs.prototype.clearHandlers = function (args) {\n var handlerMap;\n var m = this.sceneNode._manager;\n if (args.handlerType == kb3d.eHandler.click) {\n handlerMap = m.clickHandlers;\n }\n else if (args.handlerType == kb3d.eHandler.doubleClick) {\n handlerMap = m.doubleClickHandlers;\n }\n else if (args.handlerType == kb3d.eHandler.draggable) {\n handlerMap = m.draggables;\n }\n else if (args.handlerType == kb3d.eHandler.hotspot) {\n handlerMap = m.hotspotClickHandlers;\n }\n if (handlerMap) {\n if (args.tag) {\n handlerMap.deleteByTag(args.tag);\n }\n else {\n handlerMap.clear();\n }\n }\n };\n Kb3dSceneRuleArgs.prototype.animate = function (args) {\n var nodes = new Array();\n if (args.node) {\n nodes = [args.node];\n }\n else {\n nodes = this.sceneNode._manager.getNodesByIdOrName(args.id, true);\n }\n var promises = new Array();\n for (var _i = 0, nodes_2 = nodes; _i < nodes_2.length; _i++) {\n var node = nodes_2[_i];\n var toValue = this.normalizePropValue(node, args);\n var a = __assign(__assign({}, args), { toValue: toValue, node: node });\n promises.push(this.kbv.viewer.animation.queue(a));\n }\n return Promise.all(promises);\n };\n Kb3dSceneRuleArgs.prototype.frameCamera = function (args) {\n this.kbv.viewer.camera.frameCamera(args.node, args);\n };\n Kb3dSceneRuleArgs.prototype.animateCamera = function (args) {\n return this.kbv.viewer.camera.animateToViewpoint(args.viewpoint, args);\n };\n Kb3dSceneRuleArgs.prototype.create = function (args) {\n var token = kb3d.Token.withKey(args.type);\n var n = this.sceneNode._manager.create(token, args.args);\n this.addToParent(n, args.parent, token);\n return n;\n };\n Kb3dSceneRuleArgs.prototype.createSketchPath = function (args) {\n var n = this.sceneNode._manager.create(kb3d.Token.SketchPath, args.args);\n this.addToParent(n, args.parent, kb3d.Token.SketchPath);\n var controlPoints = args.controlPoints.filter(function (input) { return input && input instanceof kb3d.SketchControlPoint; });\n n.addChildren.apply(n, controlPoints);\n return n;\n };\n Kb3dSceneRuleArgs.prototype.clone = function (args) {\n var o = args.node;\n var clone = this.sceneNode._manager.clone(o);\n for (var p in args.args) {\n clone[p] = args.args[p];\n }\n var token = kb3d.Token.withKey(clone.$type);\n this.addToParent(clone, args.parent, token);\n return clone;\n };\n Kb3dSceneRuleArgs.prototype.delete = function (node) {\n if (node && node._parent) {\n node._parent.removeChildren(node);\n }\n };\n Kb3dSceneRuleArgs.prototype.getChildrenOfType = function (args) {\n var n = args.node;\n if (n instanceof kb3d.Kb3dObject) {\n var tok = kb3d.Token.withKey(args.type);\n return n.filterByType(tok);\n }\n else {\n return [];\n }\n };\n Kb3dSceneRuleArgs.prototype.searchByName = function (name) {\n return this.sceneNode._manager.getNodesByIdOrName(name, true);\n };\n Kb3dSceneRuleArgs.prototype.getActiveCamera = function () {\n return this.kbv.viewer.camera.activeCamera;\n };\n Kb3dSceneRuleArgs.prototype.highlight = function (args) {\n var _this = this;\n this.kbv.viewer.forceAndWaitForNextRender().then(function () {\n //wait for next render to make sure the mesh exists before highlighting\n var nodes = _this.sceneNode._manager.getNodesByIdOrName(args.id);\n for (var _i = 0, nodes_3 = nodes; _i < nodes_3.length; _i++) {\n var n = nodes_3[_i];\n if (n instanceof kb3d.SpaceNode) {\n if (args.on) {\n _this.kbv.viewer.highlighter.add(n, _this.convertColor(args.color, enums.eColorFormat.kbcolor));\n }\n else {\n _this.kbv.viewer.highlighter.remove(n);\n }\n }\n }\n });\n };\n Kb3dSceneRuleArgs.prototype.clearHighlights = function () {\n this.kbv.viewer.highlighter.clearAll();\n };\n Kb3dSceneRuleArgs.prototype.activateGizmo = function (args) {\n var _this = this;\n var attachMesh;\n // Rotation with override space node doesn't function well. Disable that functionality so people don't try to use it,\n // Until we can swap axis/angle gizmo in and fix the transform space conversion\n if (args.gizmo === 'rotate') {\n delete args.overrideSpaceNode;\n }\n if (args.overrideSpaceNode) {\n attachMesh = args.overrideSpaceNode;\n }\n else {\n attachMesh = args.node;\n }\n var mesh = args.node;\n this.kbv.viewer.gizmos.clearGizmo();\n if (args.gizmo === 'rotate') {\n var updates = this.kbv.viewer.gizmos.rotate([attachMesh], undefined, undefined, args.axisVisibility);\n var startQ_1 = kb3d.KbQuaternion.FromRotationAxis(mesh.rotationAxis, mesh.rotationAngle);\n var startEuler_1 = mesh.eulerRotation.clone();\n updates.update.subscribe(function (updates) {\n mesh._primeMover = true;\n updates.forEach(function (update, index) {\n mesh.position = mesh.position.add(update.position);\n var qGizmo = kb3d.KbQuaternion.FromYawPitchRoll(update.rotation);\n if (!args.overrideSpaceNode) {\n if (mesh.useEuler) {\n mesh.eulerRotation = mesh.eulerRotation.add(update.rotation);\n }\n else {\n var q = kb3d.KbQuaternion.FromRotationAxis(mesh.rotationAxis, mesh.rotationAngle);\n var z = kb3d.KbQuaternion.FromYawPitchRoll(update.rotation);\n var result = q.multiply(z);\n mesh.rotationAngle = result.getAngle();\n mesh.rotationAxis = result.getAxis();\n }\n return;\n }\n else {\n var bnode = _this.kbv.viewer.getRendererNode(args.node);\n if (bnode) {\n var inSpace = bnode.parent ? bnode.parent.computeWorldMatrix(true) : undefined;\n var transform = kb3d.applyTransformToSpace(update.worldTransformMatrix, inSpace);\n qGizmo = transform.rotation;\n }\n if (mesh.useEuler) {\n mesh.eulerRotation = startEuler_1.add(qGizmo.toEuler());\n }\n else {\n var result = startQ_1.multiply(qGizmo);\n mesh.rotationAngle = result.getAngle();\n mesh.rotationAxis = result.getAxis();\n }\n }\n });\n });\n updates.totalDelta.subscribe(function () {\n startQ_1 = kb3d.KbQuaternion.FromRotationAxis(mesh.rotationAxis, mesh.rotationAngle);\n startEuler_1 = mesh.eulerRotation.clone();\n if (args.dropped) {\n args.dropped();\n }\n mesh._primeMover = false;\n });\n }\n else if (args.gizmo === 'position') {\n //update attachMesh \n var updates = null;\n if (args.overrideSpaceNode && args.overrideSpaceNode instanceof kb3d.SpaceNode) {\n var rotationQuaternion = args.overrideSpaceNode.getRotationQuaternion();\n updates = this.kbv.viewer.gizmos.position(args.node, undefined, args.axisVisibility, rotationQuaternion.toQuat());\n }\n else {\n updates = this.kbv.viewer.gizmos.position(attachMesh, undefined, args.axisVisibility);\n }\n if (updates) {\n updates.update.subscribe(function (newPosition) {\n mesh._primeMover = true;\n mesh.position = mesh.position.add(newPosition);\n });\n }\n if (args.dropped) {\n updates.totalDelta.subscribe(function () {\n args.dropped();\n mesh._primeMover = false;\n });\n }\n }\n };\n Kb3dSceneRuleArgs.prototype.clearGizmos = function () {\n this.kbv.viewer.gizmos.clearGizmo();\n };\n Kb3dSceneRuleArgs.prototype.activateSketchEditor = function (args) {\n var _this = this;\n this.clearSketchEditor();\n if (args.node instanceof kb3d.SketchNode) {\n this.kbv.viewer.sketchEditor.startOnPlane(args.node, {\n normal: args.axis || args.node.normal,\n intersect: args.intersect || args.node.position,\n }, {\n snapSize: args.snapSize || undefined,\n });\n if (args.modified) {\n this.kbv.viewer.sketchEditor.mouseUp.subscribe(function () {\n _this.kbv.viewer.forceAndWaitForNextRender().then(function () {\n args.modified();\n });\n });\n }\n }\n };\n Kb3dSceneRuleArgs.prototype.clearSketchEditor = function () {\n this.kbv.viewer.sketchEditor.clear();\n };\n Kb3dSceneRuleArgs.prototype.overwriteSketchWithSVG = function (args) {\n var _this = this;\n if (args.svgImage) {\n fetch(args.svgImage)\n .then(function (resp) { return resp.blob(); })\n .then(function (blob) { return _this.kbv.viewer.applySvgToSketch(args.node, blob); })\n .catch(function (e) {\n console.warn('Could not fetch image ' + args.svgImage, e);\n });\n }\n };\n Kb3dSceneRuleArgs.prototype.getAbsolutePosition = function (node) {\n var n = this.sceneNode._manager.getNodeByIdOrName(node);\n if (n) {\n var bnode = this.kbv.viewer.getRendererNode(n);\n if (bnode) {\n return kb3d.KbVector.From(bnode.getAbsolutePosition());\n }\n }\n return kb3d.KbVector.Zero();\n };\n Kb3dSceneRuleArgs.prototype.getSketchPathLength = function (path) {\n var pointsArray = [];\n path._points.forEach(function (point) {\n pointsArray.push([point.x, point.y, point.z]);\n });\n return computeLength(pointsArray);\n function computeLength(path) {\n var l = 0;\n for (var i = 1; i < path.length; i++) {\n var point = path[i];\n var prevPoint = path[i - 1];\n l += Math.hypot.apply(Math, [point[0] - prevPoint[0], point[1] - prevPoint[1], point[2] - prevPoint[2]]);\n }\n return l;\n }\n };\n Kb3dSceneRuleArgs.prototype.getBoundingBox = function (node, space) {\n if (space === void 0) { space = 'world'; }\n if (space === 'world') {\n return this.kbv.viewer.bbCache.getWorld(node);\n }\n else {\n return this.kbv.viewer.bbCache.refreshAndGet(node);\n }\n };\n Kb3dSceneRuleArgs.prototype.nodesIntersect = function (node1, node2) {\n return this.kbv.viewer.nodesIntersect(node1, node2);\n };\n Kb3dSceneRuleArgs.prototype.copyPropertiesTo = function (fromNode, toNode) {\n if (this.sceneNode && this.sceneNode._manager) {\n this.sceneNode._manager.assign(toNode, fromNode, { copyingToDifferentNode: true });\n }\n };\n Kb3dSceneRuleArgs.prototype.getMateChain = function (node) {\n var activeMates = this.kbv.viewer.getActiveMates();\n return __spreadArray([node], Array.from(kb3d.getNodeChain(node, activeMates)), true);\n };\n Kb3dSceneRuleArgs.prototype.rotate = function (args) {\n args.node.rotate(args.axis, args.angle);\n };\n Kb3dSceneRuleArgs.prototype.callSceneFunction = function (args, config) {\n if (!this.kbv) {\n console.warn(\"Scene function \".concat(args.name, \" was called but a scene is not loaded.\"));\n return Promise.reject();\n }\n return this.kbv.runSceneFunction(args, config).then(function (r) { return r.parameters.returnValue; });\n };\n Kb3dSceneRuleArgs.prototype.waitForNextRender = function () {\n return this.kbv.viewer.forceAndWaitForNextRender();\n };\n Kb3dSceneRuleArgs.prototype.convertAxisAngleToEuler = function (axis, angle) {\n var q = kb3d.KbQuaternion.FromRotationAxis(axis, angle);\n return q.toEuler().round(0.0000001); //round out floating point errors\n };\n Kb3dSceneRuleArgs.prototype.getGlobalMaterialNode = function (id) {\n var _this = this;\n return new Promise(function (resolve, reject) {\n return _this.kbv.viewer.rendererManager.material\n .loadGlobalMaterial(id, _this.sceneNode._manager.services)\n .subscribe(resolve, reject);\n });\n };\n Kb3dSceneRuleArgs.prototype.addToParent = function (node, parent, childToken) {\n if (parent) {\n parent.addChildren(node);\n }\n };\n Kb3dSceneRuleArgs.prototype.digestEvent = function (ev) {\n var _this = this;\n return function (a) {\n ev(a);\n _this.kbv.$scope.$digest();\n };\n };\n return Kb3dSceneRuleArgs;\n }());\n var Kb3dSceneFunctionRuleArgs = /** @class */ (function (_super) {\n __extends(Kb3dSceneFunctionRuleArgs, _super);\n function Kb3dSceneFunctionRuleArgs(kbv) {\n var _this = _super.call(this, kbv) || this;\n _this.kbv = kbv;\n return _this;\n }\n return Kb3dSceneFunctionRuleArgs;\n }(Kb3dSceneRuleArgs));\n\n var CacheBusterInterceptor = /** @class */ (function () {\n function CacheBusterInterceptor($injector, $rootScope, $templateCache, $q) {\n var _this = this;\n this.$injector = $injector;\n this.$rootScope = $rootScope;\n this.$templateCache = $templateCache;\n this.$q = $q;\n return {\n request: function (config) {\n // if it's already in the templatecache, then just get it from there\n if ($templateCache.get(config.url)) {\n return config;\n }\n if (config.method == \"GET\") {\n // we only cache-bust stuff from our own server. Presumably these requests will have a relative url\n if (!_tools.Utils.isAbsoluteUrl(config.url)) {\n var extension = _tools.Utils.getExtension(config.url) || \"\";\n extension = extension.toLowerCase();\n // non file calls in the test and prod environments should send the last deploy,\n // which allows the browser cache to store results for some calls\n var company = _this.$rootScope.company;\n var env = _this.$rootScope.environment;\n if (env != enums.eEnvironment.dev) {\n var lastDeploy = (env == enums.eEnvironment.test ? company.lastTestDeployment : company.lastProdDeployment);\n if (!extension) {\n var prefix = \"?\";\n if (config.url.search(\"\\\\?\") !== -1) {\n prefix = \"&\";\n }\n config.url += \"\".concat(prefix, \"d=\").concat(lastDeploy, \"&v=\").concat($rootScope.cacheBuster);\n }\n }\n }\n }\n return config;\n }\n };\n }\n CacheBusterInterceptor = __decorate([\n NgInterceptor({\n token: Token.CacheBusterInterceptor,\n dependencies: [\n Token.$Injector,\n Token.$RootScope,\n Token.$TemplateCache,\n Token.$Q,\n ]\n })\n ], CacheBusterInterceptor);\n return CacheBusterInterceptor;\n }());\n\n var ErrorInterceptor = /** @class */ (function () {\n function ErrorInterceptor($injector, $rootScope, $q) {\n this.$injector = $injector;\n this.$rootScope = $rootScope;\n this.$q = $q;\n return {\n response: function (response) {\n return response;\n },\n responseError: function (response) {\n var $http = $injector.get(\"$http\");\n var config = response.config;\n if (!config.ignoreErrors) {\n switch (response.status) {\n case 400:\n case 401:\n case 0:\n break;\n default:\n var msg = void 0;\n msg = \"status: \" + response.status + \"\\n\";\n msg += \"data: \\n\" + angular.toJson(response.data);\n alert(msg);\n break;\n }\n }\n return $q.reject(response);\n }\n };\n }\n ErrorInterceptor = __decorate([\n NgInterceptor({\n token: Token.ErrorInterceptor,\n dependencies: [\n Token.$Injector,\n Token.$RootScope,\n Token.$Q,\n ]\n })\n ], ErrorInterceptor);\n return ErrorInterceptor;\n }());\n\n var ForbiddenReason = /** @class */ (function () {\n function ForbiddenReason() {\n }\n ForbiddenReason.SsoNoGroups = \"SsoNoGroups\";\n ForbiddenReason.InsufficientPermissions = \"InsufficientPermissions\";\n return ForbiddenReason;\n }());\n var SecurityInterceptor = /** @class */ (function () {\n function SecurityInterceptor($injector, securityRetryQueue, $rootScope, $q) {\n this.$injector = $injector;\n this.securityRetryQueue = securityRetryQueue;\n this.$rootScope = $rootScope;\n this.$q = $q;\n return {\n request: function (request) {\n if ($rootScope.isSfdcCpq) {\n request.headers[\"kb-context\"] = \"sfdccpq\";\n }\n return request;\n },\n response: function (response) {\n return response;\n },\n responseError: function (response) {\n var config = (response.config);\n if (!config.ignoreSecurity) {\n var $http_1 = $injector.get(\"$http\");\n var promise = void 0;\n if (response.status === 401) {\n // if a request set the config to ignore auth, then we don't add the item for replay\n if (!response.config.doNotReplay) {\n promise = securityRetryQueue.pushRetryFn(\"unauthorized-server\", function () { return $http_1(response.config); });\n }\n $rootScope.user = null;\n $rootScope.$broadcast(_tools.events.loginRequested);\n if (promise) {\n return promise;\n }\n }\n if (response.status === 403) {\n if (response.data == ForbiddenReason.SsoNoGroups) {\n alert(\"We could not find proper permissions for this user. Please contact your system administrator for assistance.\");\n $rootScope.$broadcast(_tools.events.loginRequested);\n }\n else {\n $rootScope.$broadcast(_tools.events.permissionDenied);\n }\n }\n }\n return $q.reject(response);\n }\n };\n }\n SecurityInterceptor = __decorate([\n NgInterceptor({\n token: Token.SecurityInterceptor,\n dependencies: [\n Token.$Injector,\n Token.SecurityRetryService,\n Token.$RootScope,\n Token.$Q,\n ]\n })\n ], SecurityInterceptor);\n return SecurityInterceptor;\n }());\n\n var ApiService = /** @class */ (function () {\n function ApiService($http, $q, $rootScope, $location) {\n this.$http = $http;\n this.$q = $q;\n this.$rootScope = $rootScope;\n this.$location = $location;\n // public injection(): any[] {\n // return [\n // Token.$Http,\n // Token.$Q,\n // ApiService\n // ];\n // }\n this.adminProducts = new AdminProductClient(this.$http, this.$q, \"/api/admin/products\");\n this.automationStudio = new AutomationStudioClient(this.$http, this.$q, \"/api/automationstudio\");\n this.builders = new CrudClient(this.$http, this.$q, \"/api/builders\");\n this.buildTypes = new CrudClient(this.$http, this.$q, \"/api/buildtypes\");\n this.builderSettings = new SingletonCrudClient(this.$http, this.$q, \"/api/buildersettings\");\n this.categories = new CategoriesClient(this.$http, this.$q, \"/api/categories\");\n this.changePassword = new CrudClient(this.$http, this.$q, \"/api/users/changepassword\");\n this.channels = new CrudClient(this.$http, this.$q, \"/api/channels\");\n this.companies = new CrudClient(this.$http, this.$q, \"/api/companies\");\n this.configurators = new ConfiguratorClient(this.$http, this.$q, \"/api/admin/products\");\n this.contacts = new CrudClient(this.$http, this.$q, \"/api/contacts\");\n this.currencies = new CurrencyClient(this.$http, this.$q, \"/api/currencies\");\n this.customActions = new CrudClient(this.$http, this.$q, \"/api/customactions\");\n this.customers = new CrudClient(this.$http, this.$q, \"/api/customers\");\n this.dashboard = new SingletonCrudClient(this.$http, this.$q, \"/api/dashboard\");\n this.dbTables = new DbTablesClient(this.$http, this.$q, \"/api/dbtables\");\n this.deployments = new DeploymentClient(this.$http, this.$q, \"/api/deployments\");\n this.emailTemplates = new CrudClient(this.$http, this.$q, \"/api/emailtemplates\");\n this.functions = new CrudClient(this.$http, this.$q, \"/api/functions\");\n this.generators = new GeneratorClient(this.$http, this.$q, \"/api/generators\");\n this.globalDefinitions = new CrudClient(this.$http, this.$q, \"/api/globaldefinitions\");\n this.integrationSettings = new IntegrationSettingsClient(this.$http, this.$q, \"/api/integrationsettings\");\n this.jobs = new JobsClient(this.$http, this.$q, \"/api/jobs\");\n this.kinetic = new KineticClient(this.$http, this.$q, \"/api/kinetic\");\n this.languages = new LanguageClient(this.$http, this.$q, \"/api/languages\");\n this.layouts = new LayoutClient(this.$http, this.$q, \"/api/layouts\");\n this.logs = new CrudClient(this.$http, this.$q, \"/api/logs\");\n this.notifications = new NotificationClient(this.$http, this.$q, \"/api/notifications\");\n this.notificationSettings = new SingletonCrudClient(this.$http, this.$q, \"/api/notificationsettings\");\n this.optionFilters = new OptionFilterClient(this.$http, this.$q, \"/api/optionfilters\");\n this.outputBuilders = new CrudClient(this.$http, this.$q, \"/api/builders\");\n this.permissions = new PermissionClient(this.$http, this.$q, \"/api/permissions\");\n this.priceColumns = new PriceColumnClient(this.$http, this.$q, \"/api/pricecolumns\");\n this.products = new ProductClient(this.$http, this.$q, \"/api/products\");\n this.productHistory = new ProductHistoryClient(this.$http, this.$q, \"/api/producthistory\");\n this.productRules = new SingletonCrudClient(this.$http, this.$q, \"/api/productrules\");\n this.queues = new CrudClient(this.$http, this.$q, \"/api/queues\");\n this.quoteHeaders = new QuoteHeaderClient(this.$http, this.$q, \"/api/quoteheaders\");\n this.quoteOutputs = new CrudClient(this.$http, this.$q, \"/api/quoteoutputs\");\n this.quotes = new QuoteClient(this.$http, this.$q, \"/api/quotes\");\n this.quoteProducts = new CrudClient(this.$http, this.$q, \"/api/quoteproducts\");\n this.roles = new CrudClient(this.$http, this.$q, \"/api/roles\");\n this.safeFunctions = new SafeFunctionClient(this.$http, this.$q, \"/api/functions\");\n this.savedSearches = new SavedSearchClient(this.$http, this.$q, \"/api/savedsearches\");\n this.scenes = new ScenesClient(this.$http, this.$q, this.$rootScope, \"/api/scenes\");\n this.sceneHistory = new SceneHistoryClient(this.$http, this.$q, '/api/scenehistory');\n this.settings = new CompanySettingsClient(this.$http, this.$q, \"/api/settings\");\n this.tables = new TablesClient(this.$http, this.$q, \"/api/tables\");\n this.tags = new CrudClient(this.$http, this.$q, \"/api/tags\");\n this.testBuilds = new TestBuildClient(this.$http, this.$q, \"/api/testbuilds\");\n this.themes = new CrudClient(this.$http, this.$q, \"/api/themes\");\n this.tools = new ToolsClient(this.$http, this.$q, \"api/tools\");\n this.translate = new TranslateClient(this.$http, this.$q, \"api/translate\");\n this.users = new UserClient(this.$http, this.$q, \"/api/users\");\n this.workflows = new WorkflowsClient(this.$http, this.$q, \"/api/workflows\");\n this.workflowSelectors = new SingletonCrudClient(this.$http, this.$q, \"/api/workflowselector\");\n this.dbWhitelist = new DbWhitelistClient(this.$http, this.$q, \"/api/dbwhitelist\");\n this.dbXuserCreds = new DbXuserCred(this.$http, this.$q, \"/api/dbxuser\");\n this.interactions = new CrudClient(this.$http, this.$q, \"/api/interactions\");\n this.kineticMom = new KineticMomClient(this.$http, this.$q, \"/api/mom\");\n var queryString = $location.search();\n var cookieToken = queryString[\"cookieToken\"];\n if (cookieToken) {\n $http.defaults.headers.common[\"x-embed-token\"] = cookieToken;\n }\n }\n ApiService.prototype.getProxyClient = function (entityTypeName, admin) {\n var t = entityTypeName.toCamelCase();\n if (t.startsWith(\"kb\"))\n t = t.substr(2);\n if (t.toLowerCase() == \"useredit\")\n t = \"user\";\n t = t.endsWith(\"y\") ? t.substr(0, t.length - 1) + \"ies\" : t + \"s\";\n if (t.startsWith(\"company\"))\n t = t.substr(7);\n t = t.toCamelCase();\n var service = this[t];\n if (admin) {\n if (service == this.products)\n service = this.adminProducts;\n if (t.toLowerCase() == \"companysettings\")\n service = this.settings;\n }\n return service;\n };\n ApiService = __decorate([\n NgService({\n token: Token.ApiService,\n dependencies: [\n Token.$Http,\n Token.$Q,\n Token.$RootScope,\n Token.$Location\n ]\n })\n ], ApiService);\n return ApiService;\n }());\n var CrudClient = /** @class */ (function () {\n function CrudClient($http, $q, baseUrl) {\n this.$http = $http;\n this.$q = $q;\n this.baseUrl = baseUrl;\n }\n CrudClient.prototype.getById = function (id, tracker) {\n return this.$http.get(\"\".concat(this.baseUrl, \"/\").concat(id), { tracker: tracker }).then(function (r) { return r.data; });\n };\n CrudClient.prototype.getFromEnvironment = function (id, env, tracker) {\n return this.$http.get(\"\".concat(this.baseUrl, \"/\").concat(id, \"/diff\"), { params: { env: env }, tracker: tracker }).then(function (r) { return r.data; });\n };\n CrudClient.prototype.edit = function (model, tracker, waitForRefresh) {\n if (waitForRefresh === void 0) { waitForRefresh = false; }\n return this.$http.put(\"\".concat(this.baseUrl, \"/\").concat(model.id, \"?waitForRefresh=\").concat(waitForRefresh), model, { tracker: tracker }).then(function (r) { return r.data; });\n };\n CrudClient.prototype.insert = function (model, tracker, waitForRefresh) {\n if (waitForRefresh === void 0) { waitForRefresh = false; }\n return this.$http.post(\"\".concat(this.baseUrl, \"?waitForRefresh=\").concat(waitForRefresh), model, { tracker: tracker }).then(function (r) { return r.data; });\n };\n CrudClient.prototype.upsert = function (model, tracker, waitForRefresh) {\n if (waitForRefresh === void 0) { waitForRefresh = false; }\n if (model.id) {\n return this.edit(model, tracker, waitForRefresh);\n }\n else {\n return this.insert(model, tracker, waitForRefresh);\n }\n };\n CrudClient.prototype.delete = function (id, tracker, ignoreSecurity) {\n if (ignoreSecurity === void 0) { ignoreSecurity = false; }\n return this.$http.delete(\"\".concat(this.baseUrl, \"/\").concat(id), { tracker: tracker, ignoreSecurity: ignoreSecurity });\n };\n CrudClient.prototype.clone = function (id, tracker) {\n return this.$http.post(\"\".concat(this.baseUrl, \"/\").concat(id, \"/clone\"), null, { tracker: tracker }).then(function (r) { return r.data; });\n };\n CrudClient.prototype.getPaged = function (p, tracker) {\n return this.$http.get(this.baseUrl, { params: p, tracker: tracker }).then(function (r) { return r.data.items; });\n };\n CrudClient.prototype.searchPaged = function (p, tracker) {\n return this.$http.post(this.baseUrl + \"/searchPaged\", p).then(function (r) { return r.data.items; });\n };\n CrudClient.prototype.getBatch = function (request, tracker) {\n return this.$http.get(\"\".concat(this.baseUrl, \"/batch\"), { params: request, tracker: tracker }).then(function (r) { return r.data; });\n };\n CrudClient.prototype.search = function (args, tracker) {\n // fill in args with defaults\n var defaultArgs = {\n query: null,\n fields: null,\n sortField: \"name\",\n descending: false,\n skip: 0,\n take: 10000\n };\n var fullArgs = _tools.Utils.extend({}, defaultArgs, args);\n return this.$http.post(\"\".concat(this.baseUrl, \"/search\"), fullArgs, { tracker: tracker }).then(function (r) { return r.data; });\n };\n CrudClient.prototype.suggest = function (args) {\n if (args.query) {\n return this.$http.post(\"\".concat(this.baseUrl, \"/suggest\"), args).then(function (r) { return r.data; });\n }\n else {\n return this.$q.when([]);\n }\n };\n CrudClient.prototype.uniqueValues = function (args) {\n return this.$http.post(\"\".concat(this.baseUrl, \"/uniquevalues\"), args).then(function (r) { return r.data; });\n };\n CrudClient.prototype.rebuildIndex = function (tracker) {\n return this.$http.post(\"\".concat(this.baseUrl, \"/rebuildindex\"), null, { tracker: tracker });\n };\n return CrudClient;\n }());\n var AutomationStudioClient = /** @class */ (function () {\n function AutomationStudioClient($http, $q, baseUrl) {\n this.$http = $http;\n this.$q = $q;\n this.baseUrl = baseUrl;\n }\n AutomationStudioClient.prototype.getToken = function (tracker) {\n return this.$http.get(\"\".concat(this.baseUrl, \"/token\"), { tracker: tracker }).then(function (r) { return r.data; });\n };\n return AutomationStudioClient;\n }());\n var TranslateClient = /** @class */ (function () {\n function TranslateClient($http, $q, baseUrl) {\n this.$http = $http;\n this.$q = $q;\n this.baseUrl = baseUrl;\n }\n TranslateClient.prototype.translateArray = function (request, tracker) {\n return this.$http.post(\"\".concat(this.baseUrl, \"/array\"), request, { tracker: tracker }).then(function (r) { return r.data; });\n };\n return TranslateClient;\n }());\n var DeploymentClient = /** @class */ (function () {\n function DeploymentClient($http, $q, baseUrl) {\n this.$http = $http;\n this.$q = $q;\n this.baseUrl = baseUrl;\n }\n DeploymentClient.prototype.getById = function (id, tracker) {\n return this.$http.get(\"\".concat(this.baseUrl, \"/\").concat(id), { tracker: tracker }).then(function (r) { return r.data; });\n };\n DeploymentClient.prototype.getPaged = function (p, tracker) {\n return this.$http.get(this.baseUrl, { params: p, tracker: tracker })\n .then(function (r) { return r.data.items; });\n };\n DeploymentClient.prototype.deploy = function (model) {\n return this.$http.post(\"/api/deploy\", model).then(function (r) { return r.data; });\n };\n DeploymentClient.prototype.compare = function (model, tracker) {\n return this.$http.post(\"/api/deploy/compare\", model, { tracker: tracker }).then(function (r) { return r.data; });\n };\n return DeploymentClient;\n }());\n var SingletonCrudClient = /** @class */ (function () {\n function SingletonCrudClient($http, $q, baseUrl) {\n this.$http = $http;\n this.$q = $q;\n this.baseUrl = baseUrl;\n }\n SingletonCrudClient.prototype.get = function (tracker) {\n return this.$http.get(\"\".concat(this.baseUrl), { tracker: tracker }).then(function (r) { return r.data; });\n };\n SingletonCrudClient.prototype.edit = function (model, tracker) {\n return this.$http.put(\"\".concat(this.baseUrl), model, { tracker: tracker }).then(function (r) { return r.data; });\n };\n SingletonCrudClient.prototype.getFromEnvironment = function (id, env, tracker) {\n return this.$http.get(\"\".concat(this.baseUrl, \"/diff\"), { params: { env: env }, tracker: tracker }).then(function (r) { return r.data; });\n };\n SingletonCrudClient.prototype.rebuildIndex = function (tracker) {\n return this.$http.post(\"\".concat(this.baseUrl, \"/rebuildindex\"), null, { tracker: tracker });\n };\n return SingletonCrudClient;\n }());\n var PermissionClient = /** @class */ (function () {\n function PermissionClient($http, $q, baseUrl) {\n this.$http = $http;\n this.$q = $q;\n this.baseUrl = baseUrl;\n }\n PermissionClient.prototype.get = function (tracker) {\n return this.$http.get(\"\".concat(this.baseUrl), { tracker: tracker }).then(function (r) { return r.data; });\n };\n PermissionClient.prototype.save = function (model, tracker) {\n return this.$http.post(\"\".concat(this.baseUrl), model, { tracker: tracker }).then(function (r) { return r.data; });\n };\n return PermissionClient;\n }());\n var ToolsClient = /** @class */ (function () {\n function ToolsClient($http, $q, baseUrl) {\n this.$http = $http;\n this.$q = $q;\n this.baseUrl = baseUrl;\n }\n ToolsClient.prototype.runIndexOperation = function (args, tracker) {\n return this.$http.post(\"/api/search/run\", args, { tracker: tracker }).then(function (r) { return r.data; });\n };\n ToolsClient.prototype.rebuildIndex = function (tracker) {\n return this.$http.post(\"/api/search/rebuild\", null, { tracker: tracker });\n };\n ToolsClient.prototype.rebuildIndexAllEnv = function (tracker) {\n return this.$http.post(\"/api/search/rebuildallenv\", null, { tracker: tracker });\n };\n ToolsClient.prototype.rebuildIndexAll = function (tracker) {\n return this.$http.post(\"/api/search/rebuildall\", null, { tracker: tracker });\n };\n ToolsClient.prototype.rebuildRootIndex = function (tracker) {\n return this.$http.post(\"/api/search/rebuildroot\", null, { tracker: tracker });\n };\n ToolsClient.prototype.recreateStorage = function (tracker) {\n return this.$http.post(\"/api/storage/create\", null, { tracker: tracker });\n };\n ToolsClient.prototype.pullFromProduction = function (tracker) {\n return this.$http.post(\"\".concat(this.baseUrl, \"/pullfromprod\"), null, { tracker: tracker });\n };\n ToolsClient.prototype.update3DPlugin = function (tracker) {\n return this.$http.post(\"/api/debug/post-3d-plugin\", null, { tracker: tracker });\n };\n ToolsClient.prototype.recreate3D = function (tracker) {\n return this.$http.post(\"/api/recreate3d\", null, { tracker: tracker });\n };\n ToolsClient.prototype.recreateDns = function (tracker) {\n return this.$http.post(\"/api/recreatedns\", null, { tracker: tracker });\n };\n ToolsClient.prototype.cleanDb = function (args, tracker) {\n return this.$http.post(\"${this.baseUrl}/cleanDb\", args, { tracker: tracker });\n };\n ToolsClient.prototype.pullSfdcProducts = function (soqlStatement, tracker) {\n return this.$http.post(\"\".concat(this.baseUrl, \"/pullsfdcproducts\"), { whereClause: soqlStatement }, { tracker: tracker });\n };\n ToolsClient.prototype.getSearchableTypeNames = function (tracker) {\n return this.$http.get(\"/api/search/searchableTypes\", { tracker: tracker }).then(function (r) { return r.data; });\n };\n return ToolsClient;\n }());\n var PriceColumnClient = /** @class */ (function (_super) {\n __extends(PriceColumnClient, _super);\n function PriceColumnClient($http, $q, baseUrl) {\n var _this = _super.call(this, $http, $q, baseUrl) || this;\n _this.$http = $http;\n _this.$q = $q;\n _this.baseUrl = baseUrl;\n return _this;\n }\n PriceColumnClient.prototype.getPriceColumnsForUser = function (tracker) {\n return this.$http.get(\"\".concat(this.baseUrl, \"/user\")).then(function (r) { return r.data; });\n };\n PriceColumnClient.prototype.reorder = function (args, tracker) {\n return this.$http.post(\"\".concat(this.baseUrl, \"/reorder\"), args, { tracker: tracker }).then(function (r) { return r.data; });\n };\n return PriceColumnClient;\n }(CrudClient));\n var KineticClient = /** @class */ (function () {\n function KineticClient($http, $q, baseUrl) {\n this.$http = $http;\n this.$q = $q;\n this.baseUrl = baseUrl;\n }\n KineticClient.prototype.getDocumentRulesSchema = function (idConfig) {\n return this.$http.get(\"\".concat(this.baseUrl, \"/documentRuleSchema/\").concat(idConfig), null);\n };\n KineticClient.prototype.getDocumentRulesSchemaForDynamicAttributes = function (idConfig, company) {\n return this.$http.get(\"\".concat(this.baseUrl, \"/documentRuleSchema/\").concat(idConfig, \"/\").concat(company), null);\n };\n KineticClient.prototype.testConnection = function () {\n return this.$http.get(\"\".concat(this.baseUrl, \"/test\"), null);\n };\n return KineticClient;\n }());\n var JobsClient = /** @class */ (function (_super) {\n __extends(JobsClient, _super);\n function JobsClient($http, $q, baseUrl) {\n var _this = _super.call(this, $http, $q, baseUrl) || this;\n _this.$http = $http;\n _this.$q = $q;\n _this.baseUrl = baseUrl;\n return _this;\n }\n JobsClient.prototype.getLogs = function (idJob, tracker) {\n return this.$http.get(\"\".concat(this.baseUrl, \"/\").concat(idJob, \"/logs\")).then(function (r) { return r.data; });\n };\n return JobsClient;\n }(CrudClient));\n var TablesClient = /** @class */ (function (_super) {\n __extends(TablesClient, _super);\n function TablesClient($http, $q, baseUrl) {\n var _this = _super.call(this, $http, $q, baseUrl) || this;\n _this.$http = $http;\n _this.$q = $q;\n _this.baseUrl = baseUrl;\n return _this;\n }\n TablesClient.prototype.updateFromSource = function (id, tracker) {\n return this.$http.post(\"\".concat(this.baseUrl, \"/\").concat(id, \"/updatefromsource\"), null, { tracker: tracker }).then(function (r) { return r.data; });\n };\n return TablesClient;\n }(CrudClient));\n var WorkflowsClient = /** @class */ (function (_super) {\n __extends(WorkflowsClient, _super);\n function WorkflowsClient($http, $q, baseUrl) {\n var _this = _super.call(this, $http, $q, baseUrl) || this;\n _this.$http = $http;\n _this.$q = $q;\n _this.baseUrl = baseUrl;\n return _this;\n }\n WorkflowsClient.prototype.states = function (tracker) {\n return this.$http.get(\"/api/states\", { tracker: tracker }).then(function (r) { return r.data; });\n };\n return WorkflowsClient;\n }(CrudClient));\n var ScenesClient = /** @class */ (function (_super) {\n __extends(ScenesClient, _super);\n function ScenesClient($http, $q, $rootScope, baseUrl) {\n var _this = _super.call(this, $http, $q, baseUrl) || this;\n _this.$http = $http;\n _this.$q = $q;\n _this.$rootScope = $rootScope;\n _this.baseUrl = baseUrl;\n return _this;\n }\n ScenesClient.prototype.search = function (args, tracker) {\n args = args || {};\n args.filters = args.filters || [];\n var externalValues = [];\n if (this.$rootScope.company.kb3dEnabled)\n externalValues.push(false);\n if (this.$rootScope.company.classic3dEnabled)\n externalValues.push(true);\n args.filters.push({\n property: \"external\",\n values: externalValues\n });\n return _super.prototype.search.call(this, args, tracker);\n };\n ScenesClient.prototype.convertToKb3d = function (id, tracker) {\n return this.$http.post(\"\".concat(this.baseUrl, \"/\").concat(id, \"/convert\"), null, { tracker: tracker }).then(function (r) { return r.data; });\n };\n return ScenesClient;\n }(CrudClient));\n var SceneHistoryClient = /** @class */ (function () {\n function SceneHistoryClient($http, $q, baseUrl) {\n this.$http = $http;\n this.$q = $q;\n this.baseUrl = baseUrl;\n }\n SceneHistoryClient.prototype.getSceneHistory = function (idScene, tracker) {\n return this.$http.get(\"\".concat(this.baseUrl, \"/\").concat(idScene), { tracker: tracker }).then(function (r) { return r.data; });\n };\n SceneHistoryClient.prototype.getHistoryByIdHistory = function (idHistory, tracker) {\n return this.$http.get(\"\".concat(this.baseUrl, \"/idhist/\").concat(idHistory), { tracker: tracker }).then(function (r) { return r.data; });\n };\n SceneHistoryClient.prototype.cloneHistoryToNewScene = function (idSceneHistory, tracker) {\n return this.$http.post(\"\".concat(this.baseUrl, \"/clone/\").concat(idSceneHistory), {}, { tracker: tracker }).then(function (r) { return r.data; });\n };\n SceneHistoryClient.prototype.revertSceneToHistory = function (idSceneHistory, tracker) {\n return this.$http.post(\"\".concat(this.baseUrl, \"/revert/\").concat(idSceneHistory), {}, { tracker: tracker }).then(function (r) { return r.data; });\n };\n return SceneHistoryClient;\n }());\n var NotificationClient = /** @class */ (function (_super) {\n __extends(NotificationClient, _super);\n function NotificationClient($http, $q, baseUrl) {\n var _this = _super.call(this, $http, $q, baseUrl) || this;\n _this.$http = $http;\n _this.$q = $q;\n _this.baseUrl = baseUrl;\n return _this;\n }\n return NotificationClient;\n }(CrudClient));\n var CategoriesClient = /** @class */ (function (_super) {\n __extends(CategoriesClient, _super);\n function CategoriesClient($http, $q, baseUrl) {\n var _this = _super.call(this, $http, $q, baseUrl) || this;\n _this.$http = $http;\n _this.$q = $q;\n _this.baseUrl = baseUrl;\n return _this;\n }\n CategoriesClient.prototype.tree = function (params, tracker) {\n return this.$http.get(\"api/categories/tree\", { params: params, tracker: tracker }).then(function (r) { return r.data; });\n };\n return CategoriesClient;\n }(CrudClient));\n var OptionFilterClient = /** @class */ (function () {\n function OptionFilterClient($http, $q, baseUrl) {\n this.$http = $http;\n this.$q = $q;\n this.baseUrl = baseUrl;\n }\n OptionFilterClient.prototype.run = function (args, tracker) {\n return this.$http.post(\"\".concat(this.baseUrl, \"/run\"), args, { tracker: tracker }).then(function (r) { return r.data; });\n };\n return OptionFilterClient;\n }());\n var DbTablesClient = /** @class */ (function () {\n function DbTablesClient($http, $q, baseUrl) {\n this.$http = $http;\n this.$q = $q;\n this.baseUrl = baseUrl;\n }\n DbTablesClient.prototype.getAll = function (tracker) {\n return this.$http.get(\"\".concat(this.baseUrl), { tracker: tracker }).then(function (r) { return r.data; });\n };\n DbTablesClient.prototype.get = function (name, tracker) {\n return this.$http.get(\"\".concat(this.baseUrl, \"/\").concat(name), { tracker: tracker }).then(function (r) { return r.data; });\n };\n DbTablesClient.prototype.getAllSizeInfo = function (tracker) {\n return this.$http.get(\"\".concat(this.baseUrl, \"/sizes\"), { tracker: tracker }).then(function (r) { return r.data; });\n };\n return DbTablesClient;\n }());\n var IntegrationSettingsClient = /** @class */ (function (_super) {\n __extends(IntegrationSettingsClient, _super);\n function IntegrationSettingsClient($http, $q, baseUrl) {\n var _this = _super.call(this, $http, $q, baseUrl) || this;\n _this.$http = $http;\n _this.$q = $q;\n _this.baseUrl = baseUrl;\n return _this;\n }\n IntegrationSettingsClient.prototype.checkSfdcCredentials = function () {\n return this.$http.get(\"/api/integrationsettings/checksfdccredentials\").then(function (r) { return r.data; });\n };\n IntegrationSettingsClient.prototype.checkOracleCpqCredentials = function () {\n return this.$http.get(\"/api/integrationsettings/checkoraclecpqcredentials\").then(function (r) { return r.data; });\n };\n IntegrationSettingsClient.prototype.getSsoGroups = function (keywords) {\n return this.$http.get(\"/api/integrationsettings/ssogroups?keywords=\".concat(keywords)).then(function (r) { return r.data; });\n };\n IntegrationSettingsClient.prototype.getSsoGroupById = function (groupId) {\n return this.$http.get(\"/api/integrationsettings/ssogroup/\".concat(groupId)).then(function (r) { return r.data; });\n };\n return IntegrationSettingsClient;\n }(SingletonCrudClient));\n var CurrencyClient = /** @class */ (function (_super) {\n __extends(CurrencyClient, _super);\n function CurrencyClient($http, $q, baseUrl) {\n var _this = _super.call(this, $http, $q, baseUrl) || this;\n _this.$http = $http;\n _this.$q = $q;\n _this.baseUrl = baseUrl;\n return _this;\n }\n /**\n * gets all company currencies\n * @param tracker\n */\n CurrencyClient.prototype.all = function (tracker) {\n return this.$http.get(\"\".concat(this.baseUrl, \"/all\"), { tracker: tracker }).then(function (r) { return r.data; });\n };\n /**\n * gets a list of all currencies (not just company currencies).\n * Used for populating a select box to add new currencies.\n * @param tracker\n */\n CurrencyClient.prototype.options = function (tracker) {\n return this.$http.get(\"\".concat(this.baseUrl, \"/options\"), { tracker: tracker }).then(function (r) { return r.data; });\n };\n /**\n * gets a list of company currencies that also includes the base currency.\n * Used for populating a select box in the quote screen for example.\n * @param tracker\n */\n CurrencyClient.prototype.companyOptions = function (tracker) {\n return this.$http.get(\"\".concat(this.baseUrl, \"/companyoptions\"), { tracker: tracker }).then(function (r) { return r.data; });\n };\n /**\n * saves the company currencies.\n * @param companyCurrencies\n * @param tracker\n */\n CurrencyClient.prototype.save = function (companyCurrencies, tracker) {\n return this.$http.post(\"\".concat(this.baseUrl, \"/save\"), companyCurrencies, { tracker: tracker })\n .then(function (r) { return r.data; });\n };\n CurrencyClient.prototype.getExchangeRates = function (baseCurrency, tracker) {\n return this.$http.get(\"\".concat(this.baseUrl, \"/exchangerates/\").concat(baseCurrency || \"\"), { tracker: tracker }).then(function (r) { return r.data; });\n };\n return CurrencyClient;\n }(CrudClient));\n var LanguageClient = /** @class */ (function (_super) {\n __extends(LanguageClient, _super);\n function LanguageClient($http, $q, baseUrl) {\n var _this = _super.call(this, $http, $q, baseUrl) || this;\n _this.$http = $http;\n _this.$q = $q;\n _this.baseUrl = baseUrl;\n return _this;\n }\n /**\n * gets a list of all languages supported by CPQ (not just company languages).\n * Used for populating a select box to add new languages.\n * @param tracker\n */\n LanguageClient.prototype.supportedLanguages = function (tracker) {\n return this.$http.get(\"\".concat(this.baseUrl, \"/supported\"), { tracker: tracker }).then(function (r) { return r.data; });\n };\n return LanguageClient;\n }(CrudClient));\n var GeneratorClient = /** @class */ (function (_super) {\n __extends(GeneratorClient, _super);\n function GeneratorClient($http, $q, baseUrl) {\n var _this = _super.call(this, $http, $q, baseUrl) || this;\n _this.$http = $http;\n _this.$q = $q;\n _this.baseUrl = baseUrl;\n return _this;\n }\n GeneratorClient.prototype.next = function (id, tracker) {\n return this.$http.get(\"\".concat(this.baseUrl, \"/\").concat(id, \"/next\"), { tracker: tracker }).then(function (r) { return r.data; });\n };\n return GeneratorClient;\n }(CrudClient));\n var UserClient = /** @class */ (function (_super) {\n __extends(UserClient, _super);\n function UserClient($http, $q, baseUrl) {\n var _this = _super.call(this, $http, $q, baseUrl) || this;\n _this.$http = $http;\n _this.$q = $q;\n _this.baseUrl = baseUrl;\n return _this;\n }\n UserClient.prototype.clearProfileImage = function (userId) {\n return this.$http.delete(\"/api/users/profileimage/\".concat(userId)).then(function (r) { return r.data; });\n };\n UserClient.prototype.deleteAndAnonymize = function (userId) {\n return this.$http.delete(\"/api/users/anonymize/\".concat(userId)).then(function (r) { return r.data; });\n };\n UserClient.prototype.resetPassword = function (userId) {\n return this.$http.post(\"api/users/resetpassword/\" + userId, {}).then(function (r) { return r.data; });\n };\n UserClient.prototype.acceptPrivacyPolicy = function () {\n return this.$http.post(\"api/users/acceptprivacypolicy\", {}).then(function (r) { return r.data; });\n };\n UserClient.prototype.resetDeactivation = function (userId) {\n return this.$http.put(\"api/users/resetdeactivation/\" + userId, {}).then(function (r) { return r.data; });\n };\n return UserClient;\n }(CrudClient));\n var LayoutClient = /** @class */ (function (_super) {\n __extends(LayoutClient, _super);\n function LayoutClient($http, $q, baseUrl) {\n var _this = _super.call(this, $http, $q, baseUrl) || this;\n _this.$http = $http;\n _this.$q = $q;\n _this.baseUrl = baseUrl;\n return _this;\n }\n LayoutClient.prototype.selections = function (tracker) {\n return this.$http.get(\"\".concat(this.baseUrl, \"/selections\"), { tracker: tracker }).then(function (r) { return r.data; });\n };\n return LayoutClient;\n }(CrudClient));\n var DbWhitelistClient = /** @class */ (function () {\n function DbWhitelistClient($http, $q, baseUrl) {\n this.$http = $http;\n this.$q = $q;\n this.baseUrl = baseUrl;\n }\n DbWhitelistClient.prototype.add = function (entry, tracker) {\n return this.$http.post(this.baseUrl, entry).then(function (r) { return r.data; });\n };\n DbWhitelistClient.prototype.getAll = function (tracker) {\n return this.$http.get(this.baseUrl).then(function (r) { return r.data; });\n };\n DbWhitelistClient.prototype.delete = function (name, tracker) {\n return this.$http.delete(this.baseUrl + \"/\" + name).then(function (r) { return r.data; });\n };\n return DbWhitelistClient;\n }());\n var DbXuserCred = /** @class */ (function () {\n function DbXuserCred($http, $q, baseurl) {\n this.$http = $http;\n this.$q = $q;\n this.baseurl = baseurl;\n }\n DbXuserCred.prototype.post = function () {\n return this.$http.post(this.baseurl, null).then(function (r) { return r.data; });\n };\n return DbXuserCred;\n }());\n var KineticMomClient = /** @class */ (function () {\n function KineticMomClient($http, $q, baseUrl) {\n this.$http = $http;\n this.$q = $q;\n this.baseUrl = baseUrl;\n }\n KineticMomClient.prototype.get = function (idConfigurator, tracker) {\n return this.$http.get(this.baseUrl + \"/partRev/\" + idConfigurator).then(function (r) { return r.data; });\n };\n return KineticMomClient;\n }());\n var ConfiguratorClient = /** @class */ (function (_super) {\n __extends(ConfiguratorClient, _super);\n function ConfiguratorClient($http, $q, baseUrl) {\n var _this = _super.call(this, $http, $q, baseUrl) || this;\n _this.$http = $http;\n _this.$q = $q;\n _this.baseUrl = baseUrl;\n return _this;\n }\n ConfiguratorClient.prototype.search = function (args, tracker) {\n args = args || {};\n args.filters = args.filters || [];\n args.filters.push({\n property: enums.meta.Product.isConfigured.name,\n values: [true]\n });\n return _super.prototype.search.call(this, args, tracker);\n };\n ConfiguratorClient.prototype.searchFields = function (id) {\n return this.$http.get(\"/api/products/\".concat(id, \"/searchfields\"))\n .then(function (r) { return r.data; });\n };\n return ConfiguratorClient;\n }(CrudClient));\n var AdminProductClient = /** @class */ (function (_super) {\n __extends(AdminProductClient, _super);\n function AdminProductClient($http, $q, baseUrl) {\n var _this = _super.call(this, $http, $q, baseUrl) || this;\n _this.$http = $http;\n _this.$q = $q;\n _this.baseUrl = baseUrl;\n return _this;\n }\n AdminProductClient.prototype.search = function (args, tracker) {\n args = args || {};\n args.filters = args.filters || [];\n args.filters.push(ProductClient.getIsConfiguredFilter(false));\n return _super.prototype.search.call(this, args, tracker);\n };\n AdminProductClient.prototype.getOutput = function (idProduct, idOutput, tracker) {\n return this.$http.get(\"/api/admin/products/\".concat(idProduct, \"/output/\").concat(idOutput)).then(function (r) { return r.data; });\n };\n return AdminProductClient;\n }(CrudClient));\n var ProductHistoryClient = /** @class */ (function () {\n function ProductHistoryClient($http, $q, baseUrl) {\n this.$http = $http;\n this.$q = $q;\n this.baseUrl = baseUrl;\n }\n ProductHistoryClient.prototype.getProductHistory = function (idProduct, tracker) {\n return this.$http.get(\"\".concat(this.baseUrl, \"/\").concat(idProduct), { tracker: tracker }).then(function (r) { return r.data; });\n };\n ProductHistoryClient.prototype.getHistoryByIdHistory = function (idHistory, tracker) {\n return this.$http.get(\"\".concat(this.baseUrl, \"/idhist/\").concat(idHistory), { tracker: tracker }).then(function (r) { return r.data; });\n };\n ProductHistoryClient.prototype.cloneHistoryToNewProduct = function (idProductHistory, tracker) {\n return this.$http.post(\"\".concat(this.baseUrl, \"/clone/\").concat(idProductHistory), {}, { tracker: tracker }).then(function (r) { return r.data; });\n };\n ProductHistoryClient.prototype.revertProductToHistory = function (idProductHistory, tracker) {\n return this.$http.post(\"\".concat(this.baseUrl, \"/revert/\").concat(idProductHistory), {}, { tracker: tracker }).then(function (r) { return r.data; });\n };\n return ProductHistoryClient;\n }());\n var ProductClient = /** @class */ (function (_super) {\n __extends(ProductClient, _super);\n function ProductClient($http, $q, baseUrl) {\n var _this = _super.call(this, $http, $q, baseUrl) || this;\n _this.$http = $http;\n _this.$q = $q;\n _this.baseUrl = baseUrl;\n return _this;\n }\n ProductClient.prototype.run = function (id, isTest, fast, tracker) {\n var path = (fast ? \"runfast\" : \"run?test=\".concat(isTest));\n return this.$http.get(\"\".concat(this.baseUrl, \"/\").concat(id, \"/\").concat(path), { tracker: tracker }).then(function (r) { return r.data; });\n };\n ProductClient.prototype.autocomplete = function (productId, fieldId, query, tracker) {\n return this.$http.get(\"\".concat(this.baseUrl, \"/\").concat(productId, \"/autocomplete\"), {\n params: { field: fieldId, query: query },\n tracker: tracker\n }).then(function (r) { return r.data; });\n };\n ProductClient.prototype.searchByCategory = function (args, tracker) {\n return this.$http.post(\"/api/products/searchByCategory\", args, { tracker: tracker }).then(function (r) { return r.data; });\n };\n ProductClient.getIsConfiguredFilter = function (isConfigured) {\n return {\n property: enums.meta.Product.isConfigured.name,\n values: [isConfigured]\n };\n };\n ProductClient.prototype.uniqueAttributeValues = function (args) {\n return this.$http.post(\"\".concat(this.baseUrl, \"/uniqueattributevalues\"), args).then(function (r) { return r.data; });\n };\n ProductClient.prototype.attributeRanges = function (args) {\n return this.$http.post(\"\".concat(this.baseUrl, \"/attributeranges\"), args).then(function (r) { return r.data; });\n };\n return ProductClient;\n }(CrudClient));\n var SafeFunctionClient = /** @class */ (function (_super) {\n __extends(SafeFunctionClient, _super);\n function SafeFunctionClient($http, $q, baseUrl) {\n var _this = _super.call(this, $http, $q, baseUrl) || this;\n _this.$http = $http;\n _this.$q = $q;\n _this.baseUrl = baseUrl;\n return _this;\n }\n SafeFunctionClient.prototype.run = function (id, parameters, tracker) {\n return this.$http.post(\"\".concat(this.baseUrl, \"/run/\").concat(id), parameters, { tracker: tracker }).then(function (r) {\n if (r.status == 204)\n return null; //no content result should be null to be backwards compatible\n return r.data;\n });\n };\n SafeFunctionClient.prototype.test = function (id, args, tracker) {\n return this.$http.post(\"\".concat(this.baseUrl, \"/test/\").concat(id), args, { tracker: tracker }).then(function (r) {\n if (r.status == 204)\n return null; //no content result should be null to be backwards compatible\n return r.data;\n });\n };\n return SafeFunctionClient;\n }(CrudClient));\n var QuoteClient = /** @class */ (function (_super) {\n __extends(QuoteClient, _super);\n function QuoteClient($http, $q, baseUrl) {\n var _this = _super.call(this, $http, $q, baseUrl) || this;\n _this.$http = $http;\n _this.$q = $q;\n _this.baseUrl = baseUrl;\n return _this;\n }\n QuoteClient.prototype.save = function (quote, tracker) {\n return this.$http.post(\"\".concat(this.baseUrl, \"/save\"), quote, { tracker: tracker }).then(function (r) { return r.data; });\n };\n QuoteClient.prototype.getProductBuildTypes = function (idQuote, tracker) {\n return this.$http.get(\"\".concat(this.baseUrl, \"/\").concat(idQuote, \"/productBuildTypes\"), { tracker: tracker }).then(function (r) { return r.data; });\n };\n QuoteClient.prototype.copyQuoteProduct = function (idQuote, idQuoteProduct, tracker) {\n return this.$http.post(\"\".concat(this.baseUrl, \"/\").concat(idQuote, \"/product/\").concat(idQuoteProduct, \"/copy\"), null, { tracker: tracker })\n .then(function (r) { return r.data; });\n };\n QuoteClient.prototype.getQuoteProduct = function (idQuote, idQuoteProduct, tracker) {\n return this.$http.get(\"\".concat(this.baseUrl, \"/\").concat(idQuote, \"/product/\").concat(idQuoteProduct), { tracker: tracker })\n .then(function (r) { return r.data; });\n };\n QuoteClient.prototype.insertQuoteProduct = function (idQuote, quoteProduct, tracker) {\n return this.$http.post(\"\".concat(this.baseUrl, \"/\").concat(idQuote, \"/product\"), quoteProduct, { tracker: tracker })\n .then(function (r) { return r.data; });\n };\n QuoteClient.prototype.editQuoteProduct = function (idQuote, quoteProduct, tracker) {\n return this.$http.put(\"\".concat(this.baseUrl, \"/\").concat(idQuote, \"/product/\").concat(quoteProduct.id), quoteProduct, { tracker: tracker })\n .then(function (r) { return r.data; });\n };\n QuoteClient.prototype.buildQuoteProduct = function (idQuote, idQuoteProduct, idBuildType, tracker) {\n return this.$http.post(\"\".concat(this.baseUrl, \"/\").concat(idQuote, \"/product/\").concat(idQuoteProduct, \"/build/\").concat(idBuildType), {}, { tracker: tracker }).then(function (r) { return r.data; });\n };\n QuoteClient.prototype.deleteQuoteProduct = function (idQuote, quoteProduct, tracker) {\n return this.$http.delete(\"\".concat(this.baseUrl, \"/\").concat(idQuote, \"/product/\").concat(quoteProduct.id), { tracker: tracker })\n .then(function (r) { return r.data; });\n };\n QuoteClient.prototype.submit = function (quote, tracker) {\n return this.$http.post(\"\".concat(this.baseUrl, \"/submit\"), quote, { tracker: tracker }).then(function (r) { return r.data; });\n };\n QuoteClient.prototype.runQuoteHeaderRule = function (quote, tracker) {\n return this.$http.post(\"\".concat(this.baseUrl, \"/headerrule\"), quote, { tracker: tracker }).then(function (r) { return r.data; });\n };\n return QuoteClient;\n }(CrudClient));\n var SavedSearchClient = /** @class */ (function (_super) {\n __extends(SavedSearchClient, _super);\n function SavedSearchClient($http, $q, baseUrl) {\n var _this = _super.call(this, $http, $q, baseUrl) || this;\n _this.$http = $http;\n _this.$q = $q;\n _this.baseUrl = baseUrl;\n return _this;\n }\n SavedSearchClient.prototype.mySearches = function (modelType) {\n return this.$http.get(\"\".concat(this.baseUrl, \"/\").concat(modelType)).then(function (r) { return r.data; });\n };\n return SavedSearchClient;\n }(CrudClient));\n var TestBuildClient = /** @class */ (function (_super) {\n __extends(TestBuildClient, _super);\n function TestBuildClient($http, $q, baseUrl) {\n var _this = _super.call(this, $http, $q, baseUrl) || this;\n _this.$http = $http;\n _this.$q = $q;\n _this.baseUrl = baseUrl;\n return _this;\n }\n TestBuildClient.prototype.getQueue = function (config, buildId) {\n return this.$http.post(\"\".concat(this.baseUrl, \"/\").concat(buildId, \"/queue\"), {\n config: config\n }).then(function (r) { return r.data; });\n };\n return TestBuildClient;\n }(CrudClient));\n var CompanySettingsClient = /** @class */ (function (_super) {\n __extends(CompanySettingsClient, _super);\n function CompanySettingsClient($http, $q, baseUrl) {\n var _this = _super.call(this, $http, $q, baseUrl) || this;\n _this.$http = $http;\n _this.$q = $q;\n _this.baseUrl = baseUrl;\n return _this;\n }\n CompanySettingsClient.prototype.updateSfdcCredential = function (apiUsername, apiPassword, apiToken) {\n return this.$http.post(\"\".concat(this.baseUrl, \"/sfdc-credential\"), {\n sfdcApiUsername: apiUsername,\n sfdcApiPassword: apiPassword,\n sfdcApiToken: apiToken\n });\n };\n CompanySettingsClient.prototype.editCurrencySetting = function (currencySetting, tracker) {\n return this.$http.put(\"\".concat(this.baseUrl, \"/currency\"), currencySetting, { tracker: tracker })\n .then(function (r) { return r.data; });\n };\n return CompanySettingsClient;\n }(SingletonCrudClient));\n var QuoteHeaderClient = /** @class */ (function (_super) {\n __extends(QuoteHeaderClient, _super);\n function QuoteHeaderClient($http, $q, baseUrl) {\n var _this = _super.call(this, $http, $q, baseUrl) || this;\n _this.$http = $http;\n _this.$q = $q;\n _this.baseUrl = baseUrl;\n return _this;\n }\n QuoteHeaderClient.prototype.getDefault = function () {\n return this.$http.get(\"\".concat(this.baseUrl, \"/default\")).then(function (r) { return r.data; });\n };\n QuoteHeaderClient.prototype.searchFields = function () {\n return this.$http.get(\"/api/quoteheaders/searchfields\")\n .then(function (r) { return r.data; });\n };\n return QuoteHeaderClient;\n }(CrudClient));\n\n var AuthService = /** @class */ (function () {\n function AuthService($http, securityRetryQueue, $rootScope, $q, signalrService, dialogService, $state, storageService) {\n var _this = this;\n this.$http = $http;\n this.securityRetryQueue = securityRetryQueue;\n this.$rootScope = $rootScope;\n this.$q = $q;\n this.signalrService = signalrService;\n this.dialogService = dialogService;\n this.$state = $state;\n this.storageService = storageService;\n // we need a promise that doesn't resolve until we have a real user. \n // Controllers can set this promise in the resolve property of the \n // route so that the controller won't initialize until we have a user\n var userDeferred = $q.defer();\n this.userPromise = userDeferred.promise;\n var contextDeferred = $q.defer();\n this.contextPromise = contextDeferred.promise;\n // var companyDeferred = $q.defer();\n // this.companyPromise = companyDeferred.promise;\n // var exchangeRatesDeferred = $q.defer();\n // this.exchangeRatesPromise = exchangeRatesDeferred.promise;\n // var companySettingsDeferred = $q.defer();\n // this.companySettingsPromise = companySettingsDeferred.promise;\n this.authPromise = $q.all([this.userPromise, this.contextPromise]);\n this.loadContext = function () {\n return $q.when((function () {\n var serverVm = window.serverVm;\n $rootScope.context = serverVm.context;\n $rootScope.environment = serverVm.context.environment;\n $rootScope.clusterEnv = serverVm.context.clusterEnv;\n $rootScope.cacheBuster = serverVm.context.cacheBuster;\n $rootScope.supportedLanguages = serverVm.context.supportedLanguages;\n $rootScope.clientLanguage = serverVm.context.clientLanguage;\n $rootScope.company = serverVm.context.company;\n $rootScope.companySettings = serverVm.context.companySettings;\n $rootScope.companyCurrencies = serverVm.context.companyCurrencies;\n fx.base = $rootScope.companySettings.currency.toUpperCase();\n fx.rates = {};\n $rootScope.companyCurrencies.forEach(function (cc) {\n fx.rates[cc.currency.toUpperCase()] = cc.rate;\n });\n $rootScope.kbmaxLogoPath = storageService.getAssetUrl('images/epicor_logo_white.png');\n if ($rootScope.context.channel && $rootScope.context.channel.imagePath) {\n $rootScope.companyLogoPath = storageService.getMediaUrl($rootScope.context.channel.imagePath);\n }\n else {\n $rootScope.companyLogoPath = $rootScope.companySettings.logoPath ? storageService.getMediaUrl($rootScope.companySettings.logoPath) : $rootScope.kbmaxLogoPath;\n }\n if (serverVm.context.user) {\n _this.confirmLogin(serverVm.context.user);\n }\n contextDeferred.resolve(serverVm.context);\n })());\n };\n this.login = function (email, password, rememberMe) {\n _this.loginError = null;\n if ($rootScope.user) {\n _this.logout();\n }\n return _this.$http.post(\"/api/auth/login\", { email: email, password: password, rememberMe: rememberMe }, { doNotReplay: true, tracker: $rootScope.loginTracker }).then(function (r) {\n _this.confirmLogin(r.data);\n }, function (r) {\n if (r.status == 400) {\n _this.loginError = r.data[\"\"].join(\"\\n\");\n }\n });\n };\n this.logout = function () {\n _this.$http.post(\"/api/auth/logout\", { doNotReplay: true }).then(function () {\n // reload the whole page to clear all context\n window.location.reload();\n });\n // $rootScope.user = null;\n // $rootScope.$broadcast(events.loginRequested);\n };\n $rootScope.$on(_tools.events.loginRequested, function (e) {\n $rootScope.user = null;\n });\n $rootScope.$on(_tools.events.permissionDenied, function (e) {\n _this.dialogService.alert({\n msg: \"Sorry, you do not have permission to view this.\",\n type: enums.eAlertType.error\n });\n _this.$state.go(\"kb.products\");\n });\n this.confirmLogin = function (user) {\n $rootScope.user = user;\n // resolve the deferred user promise\n userDeferred.resolve(user);\n _this.securityRetryQueue.retryAll();\n if ($rootScope.user.id != -1) {\n _this.signalrService.start().then(function () {\n $rootScope.$broadcast(_tools.events.loginSuccessful, $rootScope.user);\n });\n }\n else {\n $rootScope.$broadcast(_tools.events.loginSuccessful, $rootScope.user);\n }\n };\n this.keepAlive = function () {\n _this.$http.get(\"/api/auth/keepalive\").then(function () {\n // reload the whole page to clear all context\n // window.location.reload();\n });\n };\n this.loadContext();\n }\n AuthService.prototype.hasRole = function (role) {\n var isInRole = false;\n if (this.$rootScope.user) {\n isInRole = this.$rootScope.user.roles.some(function (r) {\n return r.role.isEqual(role);\n });\n }\n return isInRole;\n };\n AuthService.prototype.userHasRole = function (user, role) {\n var isInRole = user.roles.some(function (r) {\n if (!r.role)\n return false;\n return r.role.isEqual(role);\n });\n return isInRole;\n };\n AuthService.prototype.isAdminOrCompanyAdmin = function () {\n var bret = false;\n if (this.$rootScope.user) {\n bret = this.hasRole(\"Company Administrator\") || this.$rootScope.user.isAdmin;\n }\n return bret;\n };\n AuthService.ANONYMOUS_USER_ID = -1;\n AuthService = __decorate([\n NgService({\n token: Token.AuthService,\n dependencies: [\n Token.$Http,\n Token.SecurityRetryService,\n Token.$RootScope,\n Token.$Q,\n Token.SignalRService,\n Token.DialogService,\n Token.$State,\n Token.StorageService\n ]\n })\n ], AuthService);\n return AuthService;\n }());\n\n /**\n * base64 encoding from : http://www.webtoolkit.info/javascript-base64.html\n */\n var Base64Service = /** @class */ (function () {\n function Base64Service() {\n this.keyStr = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\";\n }\n Base64Service.prototype.encode = function (input) {\n var output = \"\";\n var chr1;\n var chr2;\n var chr3;\n var enc1;\n var enc2;\n var enc3;\n var enc4;\n var i = 0;\n do {\n chr1 = input.charCodeAt(i++);\n chr2 = input.charCodeAt(i++);\n chr3 = input.charCodeAt(i++);\n // tslint:disable:no-bitwise\n enc1 = chr1 >> 2;\n enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);\n enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);\n enc4 = chr3 & 63;\n if (isNaN(chr2)) {\n enc3 = enc4 = 64;\n }\n else if (isNaN(chr3)) {\n enc4 = 64;\n }\n output = output +\n this.keyStr.charAt(enc1) +\n this.keyStr.charAt(enc2) +\n this.keyStr.charAt(enc3) +\n this.keyStr.charAt(enc4);\n chr1 = chr2 = chr3 = \"\";\n enc1 = enc2 = enc3 = enc4 = \"\";\n } while (i < input.length);\n return output;\n };\n Base64Service.prototype.decode = function (input) {\n var output = \"\";\n var chr1;\n var chr2;\n var chr3;\n var enc1;\n var enc2;\n var enc3;\n var enc4;\n var i = 0;\n input = input.replace(\"/[^A-Za-z0-9\\+\\/\\=]/g\", \"\");\n while (i < input.length) {\n enc1 = this.keyStr.indexOf(input.charAt(i++));\n enc2 = this.keyStr.indexOf(input.charAt(i++));\n enc3 = this.keyStr.indexOf(input.charAt(i++));\n enc4 = this.keyStr.indexOf(input.charAt(i++));\n chr1 = (enc1 << 2) | (enc2 >> 4);\n chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);\n chr3 = ((enc3 & 3) << 6) | enc4;\n output = output + String.fromCharCode(chr1);\n if (enc3 != 64) {\n output = output + String.fromCharCode(chr2);\n }\n if (enc4 != 64) {\n output = output + String.fromCharCode(chr3);\n }\n }\n return output;\n };\n Base64Service = __decorate([\n NgService({\n token: Token.Base64Service,\n dependencies: []\n })\n ], Base64Service);\n return Base64Service;\n }());\n\n var BundleLoaderService = /** @class */ (function () {\n function BundleLoaderService($rootScope, $ocLazyLoad, storageService) {\n var _a;\n this.$rootScope = $rootScope;\n this.$ocLazyLoad = $ocLazyLoad;\n this.storageService = storageService;\n this._libs = (_a = {},\n _a[Token.SnapLib.key] = [\n {\n files: [\n this.getBundleUrl(\"snap.css\", true),\n this.getBundleUrl(\"loc/loc-snap.\".concat(this.$rootScope.clientLanguage, \".js\"), false)\n ]\n },\n {\n files: [\n this.getBundleUrl(\"snap.js\", true),\n this.getBundleUrl(\"kbsnap.js\", true),\n ],\n serie: true\n }\n ],\n _a[Token.HandsontableLib.key] = [\n this.getBundleUrl(\"lib/handsontable.full.min.js\", false),\n this.getBundleUrl(\"lib/handsontable.full.min.css\", false)\n ],\n _a[Token.HighchartsLib.key] = [\n this.getBundleUrl(\"lib/highcharts.js\", false)\n ],\n _a[Token.MonacoLoaderLib.key] = [\n this.getBundleUrl(\"lib/monaco-editor/min/vs/loader.js\", false)\n ],\n _a[Token.AdminLib.key] = [\n {\n files: [\n this.getBundleUrl(\"admin.js\", true),\n this.getBundleUrl(\"admin-templates.js\", false),\n this.getBundleUrl(\"loc/loc-admin.\".concat(this.$rootScope.clientLanguage, \".js\"), false)\n ],\n serie: true\n }\n ],\n _a[Token.Recaptcha.key] = [\n {\n files: [\n \"https://www.google.com/recaptcha/api.js?render=\" + this.$rootScope.recaptchaToken\n ],\n serie: true\n }\n ],\n _a[Token.Viewer.key] = [\n this.getBundleUrl(\"viewer.js\", true)\n ],\n _a[Token.Creator.key] = [\n this.getBundleUrl(\"creator.js\", true)\n ],\n _a);\n }\n BundleLoaderService.prototype.cachebuster = function (url, minifyIfNotDebug) {\n if (minifyIfNotDebug && this.$rootScope.clusterEnv != enums.eClusterEnv.dev && !this.$rootScope.context.debug) {\n var index = url.lastIndexOf(\".\");\n url = url.slice(0, index) + \".min\" + url.slice(index);\n }\n return \"\".concat(url, \"?v=\").concat(this.$rootScope.cacheBuster);\n };\n BundleLoaderService.prototype.getBundleUrl = function (relativePath, minifyIfNotDebug) {\n var url = this.storageService.getFileUrl(relativePath);\n return this.cachebuster(url, minifyIfNotDebug);\n };\n BundleLoaderService.prototype.load = function (libraries, paralell) {\n var _this = this;\n if (paralell === void 0) { paralell = true; }\n var urls = [];\n libraries.forEach(function (lib) { return urls.pushArray(_this._libs[lib.key]); });\n return this.$ocLazyLoad.load(urls, { serie: !paralell });\n };\n BundleLoaderService = __decorate([\n NgService({\n token: Token.BundleLoaderService,\n dependencies: [\n Token.$RootScope,\n Token.$OcLazyLoad,\n Token.StorageService\n ]\n })\n ], BundleLoaderService);\n return BundleLoaderService;\n }());\n\n /**\n * Acts as an aggregate service so consolidate dependencies used\n * across the crudController inherited classes\n */\n var CrudService = /** @class */ (function () {\n function CrudService($http, $stateParams, $rootScope, $state, $window, dialogService, drawerService, $q, signalrService, api, $transitions, authService, $location, $timeout, promiseTracker, kbService) {\n this.$http = $http;\n this.$stateParams = $stateParams;\n this.$rootScope = $rootScope;\n this.$state = $state;\n this.$window = $window;\n this.dialogService = dialogService;\n this.drawerService = drawerService;\n this.$q = $q;\n this.signalrService = signalrService;\n this.api = api;\n this.$transitions = $transitions;\n this.authService = authService;\n this.$location = $location;\n this.$timeout = $timeout;\n this.promiseTracker = promiseTracker;\n this.kbService = kbService;\n }\n CrudService = __decorate([\n NgService({\n token: Token.CrudService,\n dependencies: [\n Token.$Http,\n Token.$StateParams,\n Token.$RootScope,\n Token.$State,\n Token.$Window,\n Token.DialogService,\n Token.DrawerService,\n Token.$Q,\n Token.SignalRService,\n Token.ApiService,\n Token.$Transitions,\n Token.AuthService,\n Token.$Location,\n Token.$Timeout,\n Token.PromiseTracker,\n Token.KbService\n ]\n })\n ], CrudService);\n return CrudService;\n }());\n\n var DialogService = /** @class */ (function () {\n function DialogService($rootScope, $compile, $timeout, $sanitize, promiseTracker, api) {\n this.$rootScope = $rootScope;\n this.$compile = $compile;\n this.$timeout = $timeout;\n this.$sanitize = $sanitize;\n this.promiseTracker = promiseTracker;\n this.api = api;\n this.alerts = [];\n this.dialogs = [];\n }\n DialogService.prototype.progress = function (options) {\n if (!this.alerts)\n this.alerts = [];\n this.alerts.push(options);\n };\n DialogService.prototype.confirm = function (confirmMessage, yesCallback, noCallback) {\n this.dialog({\n content: confirmMessage,\n buttons: [\n new enums.DialogButton(loc.ok, _tools.icons.success, yesCallback),\n new enums.DialogButton(loc.cancel, _tools.icons.cancel, noCallback)\n ]\n });\n };\n DialogService.prototype.alert = function (alert) {\n var _this = this;\n if (!this.alerts)\n this.alerts = [];\n // handle the alert\n // build up the content (lives in msg div)\n if (alert.templateUrl || alert.template) {\n if (alert.templateUrl) {\n // if they provided a templateUrl, we'll use an ng-include to fetch it\n alert.msg = $(\"
Loading...
\"));\n }\n else if (alert.template) {\n alert.msg = $(\"
\".concat(alert.template, \"
\"));\n }\n // build a scope that we'll use to compile the content\n alert.scope = alert.scope || this.$rootScope.$new();\n // now compile the dialog with the scope\n this.$compile(alert.msg)(alert.scope);\n }\n // recommended way to handle digest to avoid async digest collisions\n this.$timeout(function () {\n _this.alerts.push(alert);\n });\n // $apply scope to ensure first value of array is applied to ui\n //this.$rootScope.$apply(); -- caused digest collisions when digest in progress\n var timeShown = alert.timeShown || 5000;\n if (alert.promise) {\n alert.inProgress = true;\n alert.promise.then(function () {\n alert.type = enums.eAlertType.success;\n if (alert.successMsg) {\n alert.msg = alert.successMsg;\n }\n }, function (reason) {\n alert.type = enums.eAlertType.error;\n if (!angular.isDefined(alert.showPromiseReasonOnFail) || alert.showPromiseReasonOnFail) {\n alert.msg = reason;\n }\n }).finally(function () {\n alert.inProgress = false;\n if (!alert.persist) {\n _this.$timeout(function () {\n _this.alerts.remove(alert);\n if (alert.scope)\n alert.scope.$destroy();\n }, timeShown);\n }\n });\n }\n else if (!alert.persist) {\n this.$timeout(function () {\n _this.alerts.remove(alert);\n if (alert.scope)\n alert.scope.$destroy();\n }, timeShown);\n }\n return alert;\n };\n DialogService.prototype.closeAlert = function (index) {\n this.alerts.splice(index, 1);\n };\n DialogService.prototype.dialog = function (options) {\n var _this = this;\n var defaultOptions = {\n type: enums.eAlertType.info,\n content: $(\"
\"),\n templateUrl: null,\n template: null,\n buttons: [],\n buttonArgs: function () { return new enums.DialogButtonArgs(); },\n scope: null\n };\n options = angular.extend({}, defaultOptions, options);\n // build up the content (lives in msg div)\n if (options.templateUrl) {\n // if they provided a templateUrl, we'll use an ng-include to fetch it\n options.content = $(\"
Loading...
\"));\n }\n else if (options.template) {\n options.content = $(options.template);\n }\n else if (angular.isString(options.content)) {\n options.content = $(\"\" + this.$sanitize(options.content) + \"\");\n }\n // build a dialog object and add it to root scope\n var kbDialog = {\n content: options.content,\n buttons: options.buttons,\n type: enums.eAlertType[options.type],\n visible: false,\n keypress: function (e) {\n if (kbDialog.buttons && kbDialog.buttons.length) {\n if (e.which == 13) {\n kbDialog.buttons[0].click();\n }\n else if (e.which == 27) { // escape\n kbDialog.buttons.last().click();\n }\n }\n },\n tracker: options.tracker,\n fullHeight: options.fullHeight\n };\n // set up a click command on each button that will call the callback with the args\n $.each(kbDialog.buttons, function (index, button) {\n button.click = function () {\n var args = options.buttonArgs();\n if (button.callback) {\n button.callback(args);\n }\n if (args.close) {\n kbDialog.visible = false;\n // give time for animation to finish before removing\n _this.$timeout(function () {\n _this.dialogs.remove(kbDialog);\n if (scope)\n scope.$destroy();\n }, 200);\n }\n };\n });\n // build a scope that we'll use to compile the content\n var scope = options.scope || this.$rootScope.$new();\n // now compile the dialog with the scope\n this.$compile(kbDialog.content)(scope);\n // add the dialog to the rootscope\n if (!this.dialogs)\n this.dialogs = [];\n this.dialogs.push(kbDialog);\n // wait for shield animation\n this.$timeout(function () {\n _this.$timeout(function () {\n kbDialog.visible = true;\n }, 10);\n }, 10);\n return kbDialog;\n };\n DialogService.prototype.input = function (options) {\n var defaultOptions = {\n msg: \"\",\n value: \"\",\n inputType: enums.eInputDialogType.text,\n buttons: null,\n source: null,\n labelField: \"\",\n valueField: \"\"\n };\n options = angular.extend({}, defaultOptions, options);\n var scope = this.$rootScope.$new();\n scope.msg = options.msg;\n scope.value = options.value;\n scope.source = options.source;\n scope.labelField = options.labelField;\n scope.valueField = options.valueField;\n var input = \"\";\n switch (options.inputType) {\n case enums.eInputDialogType.text:\n input = \"\";\n break;\n case enums.eInputDialogType.html:\n break;\n case enums.eInputDialogType.textArea:\n input = \"\";\n break;\n case enums.eInputDialogType.select:\n input = \"\" +\n \" {{item\" + (scope.labelField ? \".\" + scope.labelField : \"\") + \"}}\" +\n \" \";\n break;\n }\n var dialogOptions = {\n type: enums.eAlertType.info,\n content: $(\"
{{msg}}
\" +\n \"
\" +\n input +\n \"
\"),\n templateUrl: null,\n buttons: options.buttons,\n buttonArgs: function () {\n var args = new enums.InputDialogButtonArgs();\n args.value = scope.value;\n return args;\n },\n scope: scope\n };\n return this.dialog(dialogOptions);\n };\n DialogService.prototype.mediaSelect = function (options) {\n var defaultOptions = {\n startPath: \"\",\n buttons: null,\n filter: enums.eMediaFilter.imagesAndVideos,\n apiPath: \"api/media\",\n rootDir: \"media\",\n open: function (file) {\n window.open(file.id, \"_blank\");\n }\n };\n options = angular.extend({}, defaultOptions, options);\n var filter = \"\";\n switch (options.filter) {\n case enums.eMediaFilter.images:\n filter = _tools.extensions.image;\n break;\n case enums.eMediaFilter.videos:\n filter = _tools.extensions.video;\n break;\n case enums.eMediaFilter.imagesAndVideos:\n filter = _tools.extensions.image + \",\" + _tools.extensions.video;\n break;\n case enums.eMediaFilter.environments:\n filter = _tools.extensions.environments;\n break;\n }\n var scope = this.$rootScope.$new();\n scope.dStartPath = options.startPath;\n scope.tracker = this.promiseTracker();\n var apiPath = \"api/media\";\n if (options.apiPath)\n apiPath = options.apiPath;\n var rootDir = \"media\";\n if (options.rootDir)\n rootDir = options.rootDir;\n var dialogOptions = {\n type: enums.eAlertType.info,\n content: $('' +\n \"\"),\n templateUrl: null,\n buttons: options.buttons,\n buttonArgs: function () {\n var args = new enums.MediaDialogButtonArgs();\n if (scope.dSelected) {\n args.selectedItem = scope.dSelected;\n }\n return args;\n },\n scope: scope,\n tracker: scope.tracker\n };\n return this.dialog(dialogOptions);\n };\n DialogService = __decorate([\n NgService({\n token: Token.DialogService,\n dependencies: [\n Token.$RootScope,\n Token.$Compile,\n Token.$Timeout,\n Token.$Sanitize,\n Token.PromiseTracker,\n Token.ApiService,\n ]\n })\n ], DialogService);\n return DialogService;\n }());\n\n var DrawerService = /** @class */ (function () {\n function DrawerService($rootScope, kbService, $transitions) {\n var _this = this;\n this.$rootScope = $rootScope;\n this.kbService = kbService;\n this.$transitions = $transitions;\n this.drawers = [];\n this.showHelp = true;\n $transitions.onEnter({}, function (transition, state) {\n if (state.name) {\n // clear out drawer\n _this.drawers.clear();\n _this.pageTitle = null;\n _this.pageIcon = null;\n _this.pageType = null;\n _this.showHelp = true;\n }\n });\n }\n DrawerService.prototype.setHelpUrl = function (url) {\n if (!url)\n url = \"KBMax+CPQ\";\n this.helpUrl = \"https://cpqhelp.link/\" + url.toLowerCase();\n };\n DrawerService.prototype.addDrawer = function (icon, label, command, visible, children) {\n if (!angular.isDefined(visible)) {\n visible = true;\n }\n var drawer = {\n icon: icon,\n label: label,\n command: function () { if (!drawer.disabled)\n return command(); },\n visible: visible,\n disabled: false,\n children: children\n };\n this.drawers.push(drawer);\n return drawer;\n };\n DrawerService = __decorate([\n NgService({\n token: Token.DrawerService,\n dependencies: [\n Token.$RootScope,\n Token.KbService,\n Token.$Transitions\n ]\n })\n ], DrawerService);\n return DrawerService;\n }());\n\n var InteractionService = /** @class */ (function () {\n function InteractionService(api) {\n this.api = api;\n }\n InteractionService.prototype.record = function (idConfigurator) {\n var guid = null;\n try {\n guid = window.localStorage[\"userGuid\"];\n if (!guid) {\n guid = window.localStorage[\"userGuid\"] = _tools.Utils.shortId();\n }\n }\n catch (e) {\n guid = _tools.Utils.shortId();\n }\n return this.api.interactions.insert({\n idConfigurator: idConfigurator,\n userGuid: guid\n });\n };\n InteractionService = __decorate([\n NgService({\n token: Token.InteractionService,\n dependencies: [\n Token.ApiService\n ]\n })\n ], InteractionService);\n return InteractionService;\n }());\n\n var KbService = /** @class */ (function () {\n function KbService($rootScope, authService, $q, $timeout) {\n var _this = this;\n this.$rootScope = $rootScope;\n this.authService = authService;\n this.$q = $q;\n this.$timeout = $timeout;\n this.fxConvert = function (val, to, from) {\n if (from === void 0) { from = null; }\n if (!from)\n from = _this.$rootScope.companySettings.currency.toUpperCase();\n return fx(val).from(from).to(to.toUpperCase());\n };\n this.fly = function (sourceSelector, targetSelector, callback) {\n var $source = $(sourceSelector).eq(0);\n var $target = $(targetSelector).eq(0);\n if ($source) {\n var $fly_1 = $source.clone()\n .offset({\n top: $source.offset().top,\n left: $source.offset().left\n })\n .css({\n \"opacity\": \"0.5\",\n \"position\": \"fixed\",\n \"height\": $source.height(),\n \"width\": $source.width(),\n \"z-index\": \"1000\"\n })\n .appendTo($(\"body\"))\n .animate({\n top: $target.offset().top,\n left: $target.offset().left,\n width: $target.width(),\n height: $target.height()\n }, 800, \"easeInOutSine\", function () {\n $fly_1.remove();\n if (callback)\n callback();\n $target.effect(\"bounce\", { distance: 10, times: 5 }, 500);\n });\n }\n };\n }\n KbService.prototype.loc = function (key) {\n if (key) {\n var lkey = key.toLowerCase();\n if (loc[lkey]) {\n return loc[lkey];\n }\n }\n return key;\n };\n KbService.prototype.icon = function (key) {\n var icon = _tools.icons[key];\n if (!icon) {\n icon = key;\n }\n return icon;\n };\n KbService.prototype.getExtension = function (path) {\n if (!path) {\n return \"\";\n }\n return path.split(\".\").pop().toLowerCase();\n };\n /**\n * given a kb enum type, gives back an array of NameValue objects\n * with localized names that can be used in a kbSelect\n *\n */\n KbService.prototype.getEnumSelects = function (enm, enumName) {\n var selects = [];\n for (var name_1 in enm) {\n var locName = enumName + \"_\" + name_1 + \"_title\";\n var locValue = this.loc(locName);\n selects.push({\n name: locValue,\n value: enm[name_1]\n });\n }\n return selects;\n };\n KbService.prototype.copyDataToClipboard = function (data) {\n var _this = this;\n var $el = jQuery('

Copy the Json below and use \\'Paste Json\\' in another location.

');\n var $textarea = jQuery('');\n jQuery(\"body\").find(\".copyPopup\").remove();\n $el.append($textarea);\n this.$timeout(function () {\n var textarea = $textarea.get(0);\n $textarea.val(data);\n $textarea.focus();\n textarea.setSelectionRange(0, 999999);\n textarea.addEventListener(\"keydown\", function (ev) {\n if (ev.key == \"c\" && ev.ctrlKey) {\n _this.$timeout(function () {\n $el.remove();\n }, 1);\n }\n if (ev.key == \"Escape\") {\n _this.$timeout(function () {\n $el.remove();\n }, 1);\n }\n });\n }, 1);\n jQuery(\"body\").append($el);\n };\n KbService.prototype.pasteClipboardData = function () {\n var _this = this;\n var defer = this.$q.defer();\n jQuery(\"body\").find(\".copyPopup\").remove();\n var $el = jQuery('

Paste the Json below.

');\n var $textarea = jQuery('');\n $el.append($textarea);\n jQuery(\"body\").append($el);\n this.$timeout(function () {\n var textarea = $textarea.get(0);\n $textarea.focus();\n textarea.setSelectionRange(0, 999999);\n textarea.addEventListener(\"keydown\", function (ev) {\n if (ev.key == \"v\" && ev.ctrlKey) {\n _this.$timeout(function () {\n defer.resolve($textarea.val());\n $el.remove();\n }, 1);\n }\n if (ev.key == \"Escape\") {\n _this.$timeout(function () {\n $el.remove();\n }, 1);\n }\n });\n }, 1);\n return defer.promise;\n };\n KbService.prototype.fxConvertAsync = function (val, to) {\n var deferred = this.$q.defer();\n deferred.resolve(this.fxConvert(val, to));\n return deferred.promise;\n };\n KbService = __decorate([\n NgService({\n token: Token.KbService,\n dependencies: [\n Token.$RootScope,\n Token.AuthService,\n Token.$Q,\n Token.$Timeout\n ]\n })\n ], KbService);\n return KbService;\n }());\n\n var QuoteService = /** @class */ (function () {\n function QuoteService($rootScope, $q, kbService, $http, $state, $cookieStore, dialogService, api) {\n var _this = this;\n this.$rootScope = $rootScope;\n this.$q = $q;\n this.kbService = kbService;\n this.$http = $http;\n this.$state = $state;\n this.$cookieStore = $cookieStore;\n this.dialogService = dialogService;\n this.api = api;\n var quoteIdFromCookie;\n try {\n quoteIdFromCookie = this.getActiveQuoteData();\n }\n catch (e) {\n }\n if (quoteIdFromCookie && quoteIdFromCookie.guidToken) {\n $http.get(\"/api/quotes/guid/\" + quoteIdFromCookie.guidToken, {\n ignoreSecurity: true,\n ignoreErrors: true\n }).then(function (r) {\n if (r.data.ownedBy == $rootScope.user.id ||\n r.data.allowedActions.some(function (a) { return a.type == enums.eWorkflowAction.modifyProducts; })) {\n _this.quote = r.data;\n }\n else {\n // tslint:disable-next-line:no-console\n console.log(\"Active Quote with ID \" +\n quoteIdFromCookie.guidToken +\n \" does not have proper add product permissions. Unsetting cookie.\");\n _this.$cookieStore.remove(QuoteService_1.COOKIE_NAME);\n }\n }, function () {\n // tslint:disable-next-line:no-console\n console.log(\"Active Quote with ID \" +\n quoteIdFromCookie.guidToken +\n \" does not exist. Unsetting cookie.\");\n _this.$cookieStore.remove(QuoteService_1.COOKIE_NAME);\n });\n }\n }\n QuoteService_1 = QuoteService;\n Object.defineProperty(QuoteService.prototype, \"quote\", {\n get: function () {\n return this._quote;\n },\n set: function (val) {\n this._quote = val;\n // set the active quote in a cookie\n if (val) {\n this.storeCookie(val);\n }\n else {\n this.$cookieStore.remove(QuoteService_1.COOKIE_NAME);\n }\n },\n enumerable: false,\n configurable: true\n });\n QuoteService.prototype.storeCookie = function (quote) {\n this.$cookieStore.put(QuoteService_1.COOKIE_NAME, JSON.stringify({\n idQuote: quote.id,\n guidToken: quote.guidToken\n }));\n };\n QuoteService.prototype.getActiveQuoteData = function () {\n var cookie = this.$cookieStore.get(QuoteService_1.COOKIE_NAME);\n if (!cookie)\n return null;\n return JSON.parse(cookie);\n };\n QuoteService.prototype.getLatestQuoteProduct = function (quote) {\n var result = null;\n quote.products.forEach(function (p) {\n if (!result)\n result = p;\n else {\n if (result.id < p.id) {\n result = p;\n }\n }\n });\n return result;\n };\n QuoteService.prototype.addProduct = function (args) {\n var _this = this;\n var deferred = this.$q.defer();\n // if there is no current quote, then we need to create one,\n // add the quoteProduct to it, and save on the server\n if (!this.quote) {\n this.quote = this.getNewQuote();\n if (args.currency)\n this.quote.currency = args.currency;\n // add just the id of the product to the quote products array\n this.quote.products.push({\n idProduct: args.idProduct,\n qty: args.qty,\n configuredProduct: args.configuredProduct,\n isConfigured: (args.configuredProduct !== null && args.configuredProduct !== undefined)\n });\n // save it\n this.api.quotes.save(this.quote, this.$rootScope.contentTracker).then(function (r) {\n _this.quote = r;\n deferred.resolve(_this.getLatestQuoteProduct(r));\n });\n }\n else { // there is an active quote\n if (this.quote.idWorkflow &&\n !this.quote.allowedActions.some(function (a) { return a.type == enums.eWorkflowAction.modifyProducts; })) {\n var confirm_1 = function () {\n _this.quote = null;\n _this.addProduct(args).then(function (r) {\n deferred.resolve(_this.getLatestQuoteProduct(r));\n });\n };\n if (args.silent) {\n confirm_1();\n }\n else {\n this.dialogService.confirm(\"You cannot add products to quote '\" +\n this.quote.name +\n \"' at this time. Would you like to add it to a new quote?\", function () {\n confirm_1();\n });\n }\n }\n else {\n // first we post to the server... it has it's own logic to figure\n // out duplicates and quantities\n var newQuoteProduct_1 = {\n idProduct: args.idProduct,\n qty: args.qty,\n configuredProduct: args.configuredProduct,\n isConfigured: (args.configuredProduct !== null && args.configuredProduct !== undefined)\n };\n this.api.quotes.insertQuoteProduct(this.quote.id, newQuoteProduct_1, this.$rootScope.contentTracker).then(function (r) {\n _this.quote = r;\n deferred.resolve(_this.getLatestQuoteProduct(r));\n });\n // now we figure it out locally to get an immediate update\n var existingProduct = this.quote.products.find(function (qp) {\n return !newQuoteProduct_1.isConfigured && qp.idProduct == newQuoteProduct_1.idProduct;\n });\n if (args.addLocally) {\n if (!existingProduct) {\n this.quote.products.push(newQuoteProduct_1);\n }\n else {\n existingProduct.qty += args.qty;\n }\n }\n }\n }\n return deferred.promise;\n };\n QuoteService.prototype.canModifyProductsOfQuote = function (q) {\n return !q.idWorkflow || q.allowedActions.some(function (a) { return a.type == enums.eWorkflowAction.modifyProducts; });\n };\n QuoteService.prototype.copyProductToActiveQuote = function (idQuoteProduct) {\n var _this = this;\n var deferred = this.$q.defer();\n if (this.canModifyProductsOfQuote(this.quote)) {\n this.api.quotes.copyQuoteProduct(this.quote.id, idQuoteProduct, this.$rootScope.contentTracker).then(function (r) {\n _this.quote = r;\n deferred.resolve();\n });\n }\n else {\n this.dialogService.confirm(\"You cannot add products to quote '\" +\n this.quote.name +\n \"' at this time. Would you like to add it to a new quote?\", function () {\n _this.quote = null;\n _this.copyProductToNewQuote(idQuoteProduct).then(function () {\n deferred.resolve();\n });\n });\n }\n return deferred.promise;\n };\n QuoteService.prototype.copyProductToNewQuote = function (idQuoteProduct) {\n var _this = this;\n this.quote = this.getNewQuote();\n // save it\n return this.api.quotes.save(this.quote, this.$rootScope.contentTracker).then(function (r) {\n _this.quote = r;\n return _this.api.quotes.copyQuoteProduct(_this.quote.id, idQuoteProduct, _this.$rootScope.contentTracker).then(function (r) {\n _this.quote = r;\n });\n });\n };\n QuoteService.prototype.goToQuote = function () {\n if (this.quote) {\n this.$state.go(\"kb.quoteEdit\", { id: this.quote.id });\n }\n else {\n this.$state.go(\"kb.quoteNew\");\n }\n };\n QuoteService.prototype.getNewQuote = function () {\n return {\n name: loc.newquote,\n createdBy: this.$rootScope.user.id,\n ownedBy: this.$rootScope.user.id,\n currency: this.$rootScope.companySettings.currency,\n quoteProducts: [],\n products: [],\n discountPercentage: 0\n };\n };\n QuoteService.prototype.getQuoteById = function (id) {\n var promise;\n if (this.$rootScope.user.id != AuthService.ANONYMOUS_USER_ID) {\n promise = this.$http.get(\"/api/quotes/\" + id, { method: \"GET\", tracker: this.$rootScope.contentTracker });\n }\n else {\n var data = this.getActiveQuoteData();\n if (data && data.idQuote == id) {\n promise = this.$http.get(\"/api/quotes/guid/\" + data.guidToken, { method: \"GET\", tracker: this.$rootScope.contentTracker });\n }\n else {\n promise = this.$http.get(\"/api/quotes/\" + id, { method: \"GET\", tracker: this.$rootScope.contentTracker });\n }\n }\n return promise.then(function (data) {\n return (data ? data.data : null);\n });\n };\n var QuoteService_1;\n QuoteService.COOKIE_NAME = \"activeQuote\";\n QuoteService = QuoteService_1 = __decorate([\n NgService({\n token: Token.QuoteService,\n dependencies: [\n Token.$RootScope,\n Token.$Q,\n Token.KbService,\n Token.$Http,\n Token.$State,\n Token.$CookieStore,\n Token.DialogService,\n Token.ApiService,\n ]\n })\n ], QuoteService);\n return QuoteService;\n }());\n\n var RuleService = /** @class */ (function () {\n function RuleService($q) {\n this.$q = $q;\n this._masterRuleCache = {};\n }\n RuleService.prototype.getConfiguratorHash = function (config) {\n return \"\".concat(config.idProduct || 0, \"-\").concat(config.idScene || 0, \"-\").concat(config.idQuoteHeader || 0, \"-\").concat(config.id);\n };\n RuleService.prototype.getRuleName = function (rc) {\n return \"rule-\".concat(rc.id);\n };\n RuleService.prototype.getRuleHeader = function (rc) {\n var desc = \"\".concat(rc.ruleType.toSentence(), \" Rule\");\n if (rc.ruleType.equalsAny(enums.eRuleType.field, enums.eRuleType.action, enums.eRuleType.function, enums.eRuleType.optionFilter)) {\n desc += \" - \" + rc.name;\n }\n var stars = \"*\".repeat(Math.max(desc.length - 1, 70));\n return \"\\r\\n/\".concat(stars, \"\\r\\n * \").concat(desc, \"\\r\\n \").concat(stars, \"/\\r\\n\");\n };\n RuleService.prototype.getConfiguratorMasterRule = function (config) {\n var _this = this;\n var hash = this.getConfiguratorHash(config);\n if (!this._masterRuleCache.hasOwnProperty(hash)) {\n var globalRc = config.ruleContainers.find(function (rc) { return rc.ruleType.isEqual(enums.eRuleType.global); });\n var js_1 = globalRc ? globalRc.js + \"\\r\\n\\r\\n\" : \"\";\n var globalEventRc = config.ruleContainers.find(function (rc) { return rc.ruleType.isEqual(enums.eRuleType.globalEvent); });\n js_1 += globalEventRc ? globalEventRc.js + \"\\r\\n\\r\\n\" : \"\";\n js_1 += \"var _ruleDb = {\\r\\n\";\n var ruleContainers_1 = config.ruleContainers\n .concat(config.actions)\n .concat(config.functions)\n .concat(config.getChildrenOfType(enums.CToken.Field, enums.CToken.Button, enums.CToken.SvgViewer, enums.CToken.NestedSet, enums.CToken.RuleContainer))\n .concat(config.optionFilters);\n config.getChildrenOfType(enums.CToken.SvgViewer).forEach(function (svg) { return ruleContainers_1 = ruleContainers_1.concat(svg.ruleContainers); });\n config.referencedConfigurators.forEach(function (refConfig) { return ruleContainers_1 = ruleContainers_1.concat(refConfig.ruleContainers); });\n ruleContainers_1.forEach(function (rc) {\n if (rc.ruleType != enums.eRuleType.global && rc.js) {\n js_1 += _this.getRuleHeader(rc);\n js_1 += \"\\\"\".concat(_this.getRuleName(rc), \"\\\": \");\n var ruleJs = \"\\r\\n\\t\" + rc.js.split(\"\\n\").join(\"\\r\\n\\t\");\n if (rc.ruleType == enums.eRuleType.optionFilter) {\n js_1 += \"function(){\\r\\n\" + ruleJs + \"\\r\\n},\";\n }\n else {\n js_1 += \"function(){return Q.fcall(function () {\\r\\n\" + ruleJs + \"\\r\\n})},\";\n }\n }\n });\n js_1 += \"};\\r\\n\\r\\n\";\n js_1 += \"return _ruleDb[e.ruleName]();\";\n this._masterRuleCache[hash] = new Function(\"Q\", \"e\", js_1);\n }\n return this._masterRuleCache[hash];\n };\n RuleService.prototype.compileAsyncRule = function (js) {\n // tab out the code\n js = \"\\t\\t\" + js.split(\"\\n\").join(\"\\r\\n\\t\\t\");\n // wrap the js. We use Q.when().then(code) to make sure that errors are propogated to our promise error handler\n var rule = \"\\t\" + \"return Q.fcall(function () {\\n\" +\n js + \"\\n\" +\n \"\\t})\\n\";\n return new Function(\"Q\", \"e\", rule);\n };\n RuleService.prototype.runRuleAsync = function (parameters, fn) {\n var promise = fn(Q__namespace, parameters)\n .then(function () {\n return {\n parameters: parameters,\n hasError: false,\n error: null\n };\n }, function (error) {\n return {\n parameters: parameters,\n hasError: true,\n error: error\n };\n });\n return promise;\n };\n RuleService.prototype.runJsAsync = function (parameters, js) {\n var fn = this.compileAsyncRule(js);\n return this.runRuleAsync(parameters, fn);\n };\n RuleService.prototype.compileSyncRule = function (js) {\n return new Function(\"e\", js);\n };\n /**\n * runs the rule synchronously... Only for use in special circumstances if you know what you're doing!\n */\n RuleService.prototype.runRuleSync = function (parameters, fn) {\n var result = {};\n try {\n fn(Q__namespace, parameters);\n }\n catch (err) {\n result.hasError = true;\n result.error = err.message;\n }\n result.parameters = parameters;\n return result;\n };\n RuleService.prototype.runJsSync = function (parameters, js) {\n var fn = this.compileSyncRule(js);\n return this.runRuleSync(parameters, fn);\n };\n /**\n * runs the rule of a rule container, compiling and caching it along the way\n * @param ruleContainer\n * @param args\n */\n RuleService.prototype.runRuleContainerAsync = function (ruleContainer, args) {\n if (ruleContainer && ruleContainer.js) {\n var masterRule = this.getConfiguratorMasterRule(ruleContainer.$parentConfigurator);\n args[\"ruleName\"] = this.getRuleName(ruleContainer);\n var start_1 = _tools.Logger.logRuleStart(ruleContainer.$parentConfigurator.name, ruleContainer.ruleType);\n var promise = this.runRuleAsync(args, masterRule);\n if (_tools.Logger.writeRuleCycleLogs) {\n promise = promise.then(function (result) {\n _tools.Logger.logRuleEnd(ruleContainer.$parentConfigurator.name, ruleContainer.ruleType, start_1);\n return result;\n });\n }\n return promise;\n }\n else { // if there is no text in the rule, then don't bother running it\n var result = {\n hasError: false,\n parameters: args\n };\n return (new _rules.KPromise(result));\n }\n };\n RuleService.prototype.runRuleContainerSync = function (ruleContainer, args) {\n if (ruleContainer && ruleContainer.js) {\n var masterRule = this.getConfiguratorMasterRule(ruleContainer.$parentConfigurator);\n args[\"ruleName\"] = this.getRuleName(ruleContainer);\n return this.runRuleSync(args, masterRule);\n }\n else { // if there is no text in the rule, then don't bother running it\n var result = {\n hasError: false,\n parameters: args\n };\n return result;\n }\n };\n // /**\n // * runs the rule of a rule container, compiling and caching it along the way\n // * @param ruleContainer \n // * @param args \n // */\n // public runRuleContainerAsync(\n // ruleContainer: RuleContainer,\n // args: T\n // ): ng.IPromise> {\n // // find the cached fn, if it's already been compiled\n // if (ruleContainer && ruleContainer.js) {\n // // find or cache the compiled fn for perf\n // ruleContainer.$asyncFn = ruleContainer.$asyncFn || this.compileAsyncRule(ruleContainer.$parentConfigurator.getRuleJsFromContainer(ruleContainer));\n // return this.runRuleAsync(args, ruleContainer.$asyncFn);\n // } else { // if there is no text in the rule, then don't bother running it\n // let result: IJsResult = {\n // hasError: false,\n // parameters: args\n // };\n // return (new KPromise(result)) as any;\n // }\n // }\n // public runRuleContainerSync(\n // ruleContainer: RuleContainer,\n // args: T\n // ): IJsResult {\n // // find the cached fn, if it's already been compiled\n // if (ruleContainer && ruleContainer.js) {\n // // find or cache the compiled fn for perf\n // ruleContainer.$syncFn = ruleContainer.$syncFn || this.compileSyncRule(ruleContainer.$parentConfigurator.getRuleJsFromContainer(ruleContainer));\n // return this.runRuleSync(args, ruleContainer.$syncFn);\n // } else { // if there is no text in the rule, then don't bother running it\n // let result: IJsResult = {\n // hasError: false,\n // parameters: args\n // };\n // return result;\n // }\n // }\n RuleService.prototype.runRuleTypeAsync = function (config, ruleType, args) {\n var rc = config.ruleContainers.find(function (rc) {\n return rc.ruleType.isEqual(ruleType);\n });\n return this.runRuleContainerAsync(rc, args);\n };\n RuleService.prototype.runActionRuleByIdAsync = function (config, actionId, args) {\n var container = config.actions.find(function (a) { return a.id == actionId; });\n return this.runRuleContainerAsync(container, args);\n };\n RuleService = __decorate([\n NgService({\n token: Token.RuleService,\n dependencies: [\n Token.$Q,\n ]\n })\n ], RuleService);\n return RuleService;\n }());\n\n /**\n * Acts as an aggregate service so consolidate dependencies used\n * across the crudController inherited classes\n */\n var SearchService = /** @class */ (function () {\n function SearchService($location, $state, $http, $rootScope, dialogService, drawerService, $timeout, $q, api, base64Service, $filter) {\n this.$location = $location;\n this.$state = $state;\n this.$http = $http;\n this.$rootScope = $rootScope;\n this.dialogService = dialogService;\n this.drawerService = drawerService;\n this.$timeout = $timeout;\n this.$q = $q;\n this.api = api;\n this.base64Service = base64Service;\n this.$filter = $filter;\n }\n SearchService = __decorate([\n NgService({\n token: Token.SearchService,\n dependencies: [\n Token.$Location,\n Token.$State,\n Token.$Http,\n Token.$RootScope,\n Token.DialogService,\n Token.DrawerService,\n Token.$Timeout,\n Token.$Q,\n Token.ApiService,\n Token.Base64Service,\n Token.$Filter\n ]\n })\n ], SearchService);\n return SearchService;\n }());\n\n var SecurityRetryService = /** @class */ (function () {\n function SecurityRetryService($q) {\n this.$q = $q;\n this.retryQueue = [];\n }\n SecurityRetryService.prototype.retryAll = function () {\n while (this.retryQueue.length) {\n this.retryQueue.shift().retry();\n }\n };\n SecurityRetryService.prototype.pushRetryFn = function (reason, retryFn) {\n var _this = this;\n var deferredRetry = this.$q.defer();\n var retryItem = {\n reason: reason,\n retry: function () {\n _this.$q.when(retryFn()).then(function (value) {\n deferredRetry.resolve(value);\n }, function (value) {\n deferredRetry.reject(value);\n });\n },\n cancel: function () {\n deferredRetry.reject();\n }\n };\n this.push(retryItem);\n return deferredRetry.promise;\n };\n SecurityRetryService.prototype.push = function (retryItem) {\n this.retryQueue.push(retryItem);\n if (this.onItemAdded) {\n this.onItemAdded();\n }\n };\n SecurityRetryService = __decorate([\n NgService({\n token: Token.SecurityRetryService,\n dependencies: [\n Token.$Q,\n ]\n })\n ], SecurityRetryService);\n return SecurityRetryService;\n }());\n\n var SfdcService = /** @class */ (function () {\n function SfdcService($rootScope, $q, dialogService) {\n this.$rootScope = $rootScope;\n this.$q = $q;\n this.dialogService = dialogService;\n this.dynamicOptionsToQueryStatic = [];\n }\n /**\n * get's the record passed in through the canvas context\n */\n SfdcService.prototype.record = function () {\n if (this.$rootScope.isSfdc)\n return this.canvasRequest().context.environment.record;\n };\n SfdcService.prototype.canvasRequest = function () {\n if (this.$rootScope.isSfdc)\n return this.$rootScope.context.sfdcCanvasRequest;\n };\n /**\n * navigates to the salesforce view page of the object with the given id\n */\n SfdcService.prototype.navigateToObject = function (id) {\n Sfdc.canvas.client.publish(this.$rootScope.context.sfdcCanvasRequest.client, {\n name: \"navigateToObject\",\n payload: id\n });\n };\n SfdcService.prototype.toggleFullscreen = function () {\n Sfdc.canvas.client.publish(this.canvasRequest().client, {\n name: \"toggleFullscreen\",\n payload: {}\n });\n };\n /**\n * send a message to the visual force page hosting our canvas\n * @param msg\n */\n SfdcService.prototype.sendMessage = function (msg) {\n if (this.$rootScope.isSfdc) {\n Sfdc.canvas.client.publish(this.canvasRequest().client, {\n name: msg.name,\n payload: msg.data\n });\n }\n };\n /**\n * makes a quote the primary quote in sfdc by calling through the canvas\n * @param quote\n */\n SfdcService.prototype.makePrimaryQuote = function (quote) {\n var deferred = this.$q.defer();\n var sr = this.$rootScope.context.sfdcCanvasRequest;\n var url = sr.context.links.restUrl + \"sobjects/KBMAX__Quote__c/\" + quote.externalId;\n Sfdc.canvas.client.ajax(url, {\n client: sr.client,\n method: \"PATCH\",\n contentType: \"application/json\",\n data: JSON.stringify({\n KBMAX__Primary__c: true\n }),\n success: function (data) {\n if (data.status === 204) {\n deferred.resolve();\n }\n else {\n deferred.reject();\n }\n }\n });\n return deferred.promise;\n };\n /**\n * when integrating with steelbrick, because of their easyXdm setup, we have to wait for the canvas\n * to tell us what the id of the product is.\n */\n SfdcService.prototype.getPayloadFromSfdcCpq = function () {\n var deferred = this.$q.defer();\n var sr = this.$rootScope.context.sfdcCanvasRequest;\n Sfdc.canvas.client.subscribe(sr.client, {\n name: \"sfdccpq_payload_response\",\n onData: function (e) {\n deferred.resolve(e);\n }\n });\n Sfdc.canvas.client.publish(sr.client, {\n name: \"sfdccpq_payload_request\",\n payload: {}\n });\n return deferred.promise;\n };\n SfdcService.prototype.getProducts = function (productCodes) {\n var deferred = this.$q.defer();\n var sr = this.$rootScope.context.sfdcCanvasRequest;\n Sfdc.canvas.client.subscribe(sr.client, {\n name: \"sfdccpq_getproducts_response\",\n onData: function (e) {\n deferred.resolve(e.products);\n }\n });\n Sfdc.canvas.client.publish(sr.client, {\n name: \"sfdccpq_getproducts\",\n payload: { productCodes: productCodes }\n });\n return deferred.promise;\n };\n SfdcService.prototype.getColumnOrMetaValue = function (key, priceItem) {\n // find the price column if there is one\n if (priceItem.columns) {\n var colNames = Object.keys(priceItem.columns);\n for (var _i = 0, colNames_1 = colNames; _i < colNames_1.length; _i++) {\n var colName = colNames_1[_i];\n if (colName.isEqual(key)) {\n return priceItem.columns[colName];\n }\n }\n }\n // find the metadata property if there is one\n if (priceItem.metadata) {\n var metaNames = Object.keys(priceItem.metadata);\n for (var _a = 0, metaNames_1 = metaNames; _a < metaNames_1.length; _a++) {\n var metaName = metaNames_1[_a];\n if (metaName.isEqual(key)) {\n return priceItem.metadata[metaName];\n }\n }\n }\n return null;\n };\n SfdcService.prototype.getConfigurationAttribute = function (payload, name) {\n for (var att in payload.data.product.configurationAttributes) {\n if (!att.isEqual(\"attributes\") && att.isEqual(name)) {\n return att;\n }\n }\n return null;\n };\n SfdcService.prototype.addColumnsAndMetadataToConfigurationObject = function (payload, configurationData, item) {\n for (var col in item.columns) {\n var att = this.getConfigurationAttribute(payload, col);\n if (att) {\n configurationData[att] = item.columns[col];\n }\n }\n for (var m in item.metadata) {\n var att = this.getConfigurationAttribute(payload, m);\n if (att) {\n configurationData[att] = item.metadata[m];\n }\n }\n };\n SfdcService.prototype.buildOptions = function (payload, item, optionConfig, isDynamic) {\n var _this = this;\n if (isDynamic === void 0) { isDynamic = false; }\n if (!optionConfig) {\n var options = void 0;\n if (isDynamic)\n options = { 'Dynamic Options': [] };\n else\n options = { 'Other Options': [] };\n optionConfig = options;\n }\n //let dynamicOptionsToQuery: { item: IPriceItem, dynamicOption: ISfdcCpqPayloadOption }[] = [];\n if (isDynamic) {\n item.items.forEach(function (element, index) {\n var _a;\n var salesforceId = item.columns.salesforceId || item.metadata.salesforceId;\n var dynamicOption = {\n ProductCode: element.sku,\n Quantity: (_a = element.qty) !== null && _a !== void 0 ? _a : 1,\n configurationData: {},\n productId: '',\n selected: true\n };\n _this.addColumnsAndMetadataToConfigurationObject(payload, dynamicOption.configurationData, element);\n // if (element.sku == 'y_product')\n // dynamicOption.productId = '01t4x000008PckRAAS';\n // if (element.sku == 'z_product')\n // dynamicOption.productId = '01t4x000008PcknAAC';\n optionConfig['Dynamic Options'][index] = dynamicOption;\n if (!salesforceId) {\n _this.dynamicOptionsToQueryStatic.push({ item: element, dynamicOption: dynamicOption });\n }\n if (element.items.length) {\n var dynOptsBuild = _this.buildOptions(payload, element, optionConfig['Dynamic Options'][index].optionConfigurations, true);\n optionConfig['Dynamic Options'][index].optionConfigurations = dynOptsBuild.load;\n //this.dynamicOptionsToQueryStatic.push(...dynOptsBuild.dynOptionsToQuery);\n }\n });\n }\n else {\n item.items.forEach(function (element, index) {\n var _a;\n optionConfig['Other Options'][index] = {\n ProductCode: element.sku,\n ProductName: Object.keys({ element: element })[0],\n optionId: element.externalId,\n selected: true,\n Quantity: (_a = element.qty) !== null && _a !== void 0 ? _a : 1,\n configurationData: {},\n };\n _this.addColumnsAndMetadataToConfigurationObject(payload, optionConfig['Other Options'][index].configurationData, element);\n if (element.items.length > 0) {\n optionConfig['Other Options'][index].optionConfigurations = _this.buildOptions(payload, element, optionConfig['Other Options'][index].optionConfigurations).load;\n }\n });\n }\n return { load: optionConfig, dynOptionsToQuery: this.dynamicOptionsToQueryStatic };\n };\n SfdcService.prototype.clearNestedOptions = function (options) {\n var _this = this;\n for (var option in options) {\n options[option].forEach(function (element) {\n element.selected = false;\n if (element.optionConfigurations) {\n element.optionConfigurations = _this.clearNestedOptions(element.optionConfigurations);\n }\n });\n }\n return options;\n };\n SfdcService.prototype.saveToSfdcCpq = function (payload, priceObject) {\n var _this = this;\n var sr = this.$rootScope.context.sfdcCanvasRequest;\n // clear out old options\n for (var feature in payload.data.product.optionConfigurations) {\n if (feature.isEqual(\"Dynamic Options\")) {\n payload.data.product.optionConfigurations[feature].forEach(function (option) {\n option.Quantity = 0;\n option.selected = false;\n }); // clear out dynamic options\n }\n else {\n payload.data.product.optionConfigurations[feature].forEach(function (option) {\n return option.selected = false;\n }); // unselect all pre-defined product options\n // unselect all pre-defined product options\n payload.data.product.optionConfigurations[feature].forEach(function (option) {\n option.selected = false;\n //delete option['optionConfigurations'];\n //console.log(option.ProductCode, 'cleared');\n if (option.optionConfigurations) {\n option.optionConfigurations = _this.clearNestedOptions(option.optionConfigurations);\n }\n //option.Quantity = 0;\n });\n }\n }\n if (priceObject) {\n // first we process non-dynamic product options\n // we recurse through all the price items and try to find matching product \n // options that are not in the 'Dynamic Options' optionConfigurations object of the payload\n priceObject.items.forEach(function (item) {\n var _a;\n var foundInOptions = false;\n featureLoop: for (var feature in payload.data.product.optionConfigurations) {\n if (!feature.isEqual(\"Dynamic Options\")) {\n var options = payload.data.product.optionConfigurations[feature];\n for (var _i = 0, options_1 = options; _i < options_1.length; _i++) {\n var option = options_1[_i];\n if (item.sku == option.ProductCode) {\n option.selected = true;\n option.Quantity = (_a = item.qty) !== null && _a !== void 0 ? _a : 1;\n foundInOptions = true;\n if (item.items.length > 0) {\n option.optionConfigurations = _this.buildOptions(payload, item, option.optionConfigurations).load;\n }\n // load configuration attributes also\n // we only add configuration attributes that are defined \n // in the configurationAttributes section of the json\n option.configurationData = option.configurationData || {};\n _this.addColumnsAndMetadataToConfigurationObject(payload, option.configurationData, item);\n break featureLoop;\n }\n }\n }\n }\n if (!foundInOptions) {\n // if it's not found in the options, then we try to add it as a dynamic product option: \n // tslint:disable-next-line:max-line-length\n // https://community.steelbrick.com/t5/Developer-Guidebook/Configurator-Integration-to-Third-Party-Web-Apps/ta-p/5575\n var dynamicFeature = payload.data.product.optionConfigurations[\"Dynamic Options\"];\n // salesforceId must be defined for dynamic product options to work\n var salesforceId = item.columns.salesforceId || item.metadata.salesforceId;\n if (dynamicFeature) {\n // first see if the dynamic product option is already there\n //let dynamicOption: ISfdcCpqPayloadOption =\n // dynamicFeature.find(dynOpt => dynOpt.ProductCode && dynOpt.ProductCode.isEqual(item.sku));\n //if (dynamicOption) {\n // dynamicOption.Quantity = item.qty;\n // dynamicOption.selected = true;\n //} else {\n var dynamicOption = {\n productId: salesforceId,\n Quantity: item.qty,\n configurationData: {},\n selected: true,\n };\n if (item.items.length) {\n var dynOptsBuild = _this.buildOptions(payload, item, dynamicOption.optionConfigurations, true);\n dynamicOption.optionConfigurations = dynOptsBuild.load;\n //dynamicOptionsToQuery.push(...dynOptsBuild.dynOptionsToQuery);\n }\n dynamicFeature.push(dynamicOption);\n // if the salesforceId wasn't provided directly,\n // then we make a call later to get the product id using the product code\n if (!salesforceId) {\n _this.dynamicOptionsToQueryStatic.push({ item: item, dynamicOption: dynamicOption });\n }\n _this.addColumnsAndMetadataToConfigurationObject(payload, dynamicOption.configurationData, item);\n }\n }\n });\n // set the product level configuration attributes that correspond to price columns or price item metadata\n if (payload.data.product.configurationAttributes) {\n for (var prop in payload.data.product.configurationAttributes) {\n var attValue = this.getColumnOrMetaValue(prop, priceObject);\n if (attValue != null) {\n // priceObject corresponds to the top level product\n payload.data.product.configurationAttributes[prop] = attValue;\n }\n }\n }\n }\n var dynamicOptionsQueryPromise = new _rules.KPromise(null);\n if (this.dynamicOptionsToQueryStatic.length) {\n dynamicOptionsQueryPromise = this.getProducts(this.dynamicOptionsToQueryStatic.map(function (o) { return o.item.sku; })\n .removeNulls())\n .then(function (products) {\n _this.dynamicOptionsToQueryStatic.forEach(function (dynOption) {\n var product2 = products.find(function (p) { return p.ProductCode.isEqual(dynOption.item.sku); });\n if (!product2) {\n // tslint:disable-next-line:max-line-length\n var err = \"Unable to add dynamic product option '\".concat(dynOption.item.sku, \"'. No matching product record was found.\");\n _this.dialogService.alert({ msg: err, persist: true, type: enums.eAlertType.error });\n throw err;\n }\n else {\n dynOption.dynamicOption.productId = product2.Id;\n }\n });\n });\n }\n // DEBUG\n // if (Environment.isDebug) {\n // payload.data.quote[\"KBMAXSB__Test__c\"] = \"blah blah\";\n // }\n // payload.data.product.optionConfigurations[\"DynamicFeature\"].push({\n // productId: \"01t41000003vzS3\",\n // Quantity: 2,\n // configurationData: {\n // KBMAXSB__Test__c: \"hey now\",\n // KBMAXSB__Number_Attribute__c: 444\n // }\n // });\n // payload.data.product.optionConfigurations[\"DynamicFeature\"].push({\n // productId: \"01t41000003vzS3\",\n // Quantity: 2,\n // configurationData: {\n // KBMAXSB__Test__c: \"hey now\",\n // KBMAXSB__Number_Attribute__c: 444\n // }\n // });\n dynamicOptionsQueryPromise.then(function () {\n Sfdc.canvas.client.publish(sr.client, {\n name: \"sfdccpq_save\",\n payload: payload\n });\n });\n };\n SfdcService = __decorate([\n NgService({\n token: Token.SfdcService,\n dependencies: [\n Token.$RootScope,\n Token.$Q,\n Token.DialogService,\n ]\n })\n ], SfdcService);\n return SfdcService;\n }());\n\n //import {ConsoleLogger} from \"@aspnet/signalR\";\n //import {JsonHubProtocol} from \"@aspnet/signalR\";\n //import {LogLevel} from \"@aspnet/signalR\";\n // import * as signalR from \"@aspnet/signalr-client\";\n var SignalrService = /** @class */ (function () {\n function SignalrService($rootScope, $q) {\n this.$rootScope = $rootScope;\n this.$q = $q;\n }\n SignalrService.prototype.stop = function () {\n this.stopping = true;\n this.crudConnection.stop();\n this.notificationConnection.stop();\n };\n SignalrService.prototype.start = function () {\n // adapted from https://docs.microsoft.com/en-us/aspnet/core/signalr/javascript-client?view=aspnetcore-2.1\n // Surprise, surprise, as of today (July, 2018) HubConnectionBuilder which the documentation references\n // isn't in the npm aspnet/signalr project.\n this.crudConnection = new window.signalR.HubConnectionBuilder()\n .withUrl(\"/crudHub\", {\n serverTimeoutInMilliseconds: 100000000\n })\n .withHubProtocol(new signalR.JsonHubProtocol())\n .configureLogging(window.signalR.LogLevel.Information)\n .build();\n this.notificationConnection = new window.signalR.HubConnectionBuilder()\n .withUrl(\"/notificationHub\", {\n serverTimeoutInMilliseconds: 100000000\n })\n .withHubProtocol(new signalR.JsonHubProtocol())\n .configureLogging(window.signalR.LogLevel.Information)\n .build();\n var promises = [this.crudConnectionPromise = this.crudConnection.start(), this.notificationConnectionPromise = this.notificationConnection.start()];\n return this.$q.when(promises);\n };\n SignalrService.prototype.notificationOn = function (eventName, callback) {\n if (this.notificationConnection)\n this.notificationConnection.on(eventName, callback);\n };\n SignalrService.prototype.notificationOff = function (eventName, callback) {\n if (this.notificationConnection)\n this.notificationConnection.off(eventName, callback);\n };\n SignalrService.prototype.notificationInvoke = function (methodName) {\n var _this = this;\n var data = [];\n for (var _i = 1; _i < arguments.length; _i++) {\n data[_i - 1] = arguments[_i];\n }\n if (this.notificationConnectionPromise) {\n this.notificationConnectionPromise.then(function () {\n _this.notificationConnection.invoke.apply(_this.notificationConnection, [methodName].concat(data))\n .then(function (result) {\n _this.$rootScope.$apply(function () {\n });\n });\n });\n }\n };\n SignalrService.prototype.on = function (eventName, callback) {\n if (this.crudConnection)\n this.crudConnection.on(eventName, callback);\n };\n SignalrService.prototype.off = function (eventName, callback) {\n if (this.crudConnection)\n this.crudConnection.off(eventName, callback);\n };\n SignalrService.prototype.invoke = function (methodName) {\n var _this = this;\n var data = [];\n for (var _i = 1; _i < arguments.length; _i++) {\n data[_i - 1] = arguments[_i];\n }\n if (this.crudConnectionPromise) {\n this.crudConnectionPromise.then(function () {\n _this.crudConnection.invoke.apply(_this.crudConnection, [methodName].concat(data))\n .then(function (result) {\n _this.$rootScope.$apply(function () {\n });\n });\n });\n }\n };\n SignalrService = __decorate([\n NgService({\n token: Token.SignalRService,\n dependencies: [\n Token.$RootScope,\n Token.$Q,\n ]\n })\n ], SignalrService);\n return SignalrService;\n }());\n\n var StorageService = /** @class */ (function () {\n function StorageService($rootScope) {\n this.$rootScope = $rootScope;\n }\n StorageService.prototype.getFallbackImage = function () {\n return \"\".concat(this.$rootScope.context.publicStorageUrl, \"/assets/images/cube.png\");\n };\n StorageService.prototype.getAssetUrl = function (relativePath) {\n return \"\".concat(this.$rootScope.context.publicStorageUrl, \"/assets/\").concat(relativePath);\n };\n StorageService.prototype.getMediaUrl = function (relativePath) {\n if (_tools.Utils.isAbsoluteUrl(relativePath)) {\n return relativePath;\n }\n else {\n return \"\".concat(this.$rootScope.context.publicStorageUrl, \"/media/\").concat(relativePath);\n }\n };\n StorageService.prototype.getProfileImageUrl = function (relativePath) {\n if (_tools.Utils.isAbsoluteUrl(relativePath)) {\n return relativePath;\n }\n else {\n return \"\".concat(this.$rootScope.context.publicStorageUrl, \"/profileimages/\").concat(relativePath);\n }\n };\n /**\n * Gets the absolute url of a generic public blob file. The relativePath given must include the container in this call (like media, mesh, etc)\n * @param relativePath\n */\n StorageService.prototype.getFileUrl = function (relativePath) {\n return \"\".concat(this.$rootScope.context.publicStorageUrl, \"/\").concat(relativePath);\n };\n StorageService = __decorate([\n NgService({\n token: Token.StorageService,\n dependencies: [\n Token.$RootScope\n ]\n })\n ], StorageService);\n return StorageService;\n }());\n\n var TelemetryService = /** @class */ (function () {\n function TelemetryService($rootScope, $transitions, $location, authService) {\n var _this = this;\n this.$rootScope = $rootScope;\n this.$transitions = $transitions;\n this.$location = $location;\n this.authService = authService;\n authService.contextPromise.then(function () {\n if ($rootScope.context.appInsightsKey) {\n var snippet = {\n config: {\n instrumentationKey: $rootScope.context.appInsightsKey,\n disableAjaxTracking: true\n }\n };\n var init = new Microsoft.ApplicationInsights[\"Initialization\"](snippet);\n _this._appInsights = init.loadAppInsights();\n $transitions.onSuccess({}, function (transition) {\n var state = transition.to();\n if (state && state.name && state.url && state.name != _this.lastState && state.name != \"kb.admin\") {\n var name_1 = _this.lastState = state.name;\n if (name_1.startsWith(\"kb.\"))\n name_1 = name_1.slice(3);\n name_1 = name_1.replace(\".base.\", \".\");\n // name = name.replace(\".\", \"/\");\n // name = \"/\" + name;\n var url = [$location.protocol(), '://', $location.host(), $location.path()].join(''); //url with no query string\n _this.trackPageView(name_1, url);\n }\n });\n }\n });\n }\n TelemetryService.prototype.setDefaultProperties = function (properties) {\n if (properties === void 0) { properties = null; }\n properties = properties || {};\n if (this.$rootScope.company && this.$rootScope.company.subdomain) {\n properties.Company = this.$rootScope.company.subdomain;\n }\n properties.App = \"Client\";\n return properties;\n };\n TelemetryService.prototype.trackPageView = function (name, url, properties) {\n if (this._appInsights) {\n this._appInsights.trackPageView(name, url, this.setDefaultProperties(properties));\n }\n };\n TelemetryService.prototype.trackEvent = function (name, properties) {\n if (this._appInsights) {\n this._appInsights.trackEvent(name, this.setDefaultProperties(properties));\n }\n };\n TelemetryService.prototype.trackException = function (exception) {\n if (this._appInsights) {\n this._appInsights.trackException(exception, null, this.setDefaultProperties());\n }\n };\n TelemetryService = __decorate([\n NgService({\n token: Token.TelemetryService,\n dependencies: [\n Token.$RootScope,\n Token.$Transitions,\n Token.$Location,\n Token.AuthService\n ]\n })\n ], TelemetryService);\n return TelemetryService;\n }());\n\n var ThemeService = /** @class */ (function () {\n function ThemeService($rootScope, $http, $location, $transitions, $state) {\n var _this = this;\n this.$rootScope = $rootScope;\n this.$http = $http;\n this.$location = $location;\n this.$transitions = $transitions;\n this.$state = $state;\n this.defaultThemes = [\n {\n id: null,\n name: \"Default\",\n skin: enums.eSkin.material,\n background: \"#f2f2f2\",\n input: \"#FFFFFF\",\n header: \"#025064\",\n primary: \"#025064\",\n accent: \"#ff8873\",\n warn: \"#ff2102\",\n success: \"#049e8a\",\n border: \"#CCC\",\n dark: false,\n font: \"Roboto\",\n fontSize: 15,\n radius: 4\n },\n {\n id: -1,\n name: \"Night Launch\",\n skin: enums.eSkin.material,\n background: \"#1a1a1a\",\n input: \"#242424\",\n header: \"#bfbfbf\",\n primary: \"#424242\",\n accent: \"#ffaf47\",\n warn: \"#e0583a\",\n success: \"#22a153\",\n border: \"#575757\",\n dark: true,\n font: \"Roboto\",\n fontSize: 15,\n radius: 2\n },\n {\n id: -2,\n name: \"Valyrian Steel\",\n skin: enums.eSkin.material,\n background: \"#eeeeee\",\n input: \"#FFFFFF\",\n header: \"#535863\",\n primary: \"#535863\",\n accent: \"#ff5e00\",\n warn: \"#e33e1c\",\n success: \"#14a54a\",\n border: \"#b6c2e0\",\n dark: false,\n font: \"Roboto\",\n fontSize: 15,\n radius: 2\n },\n {\n id: -3,\n name: \"Midnight Bananas\",\n skin: enums.eSkin.classic,\n background: \"#2b2b2b\",\n input: \"#2b2b2b\",\n header: \"#33702b\",\n primary: \"#33702b\",\n accent: \"#e7f043\",\n warn: \"#e33e1c\",\n success: \"#14a54a\",\n border: \"#a6ffad\",\n dark: true,\n font: \"Roboto\",\n fontSize: 15,\n radius: 2\n },\n {\n id: -4,\n name: \"Blood Money\",\n skin: enums.eSkin.material,\n background: \"#eeeeee\",\n input: \"#ffffff\",\n header: \"#8c3333\",\n primary: \"#8c3333\",\n accent: \"#1F5454\",\n warn: \"#e33e1c\",\n success: \"#297029\",\n border: \"#b8d6d6\",\n dark: false,\n font: \"Roboto\",\n fontSize: 15,\n radius: 2\n },\n {\n id: -5,\n name: \"Apple II\",\n skin: enums.eSkin.classic,\n background: \"#000000\",\n input: \"#000000\",\n header: \"#141414\",\n primary: \"#141414\",\n accent: \"#33fe33\",\n warn: \"#e33e1c\",\n success: \"#14a54a\",\n border: \"#33fe33\",\n dark: true,\n font: \"Roboto\",\n fontSize: 15,\n radius: 2\n },\n {\n id: -6,\n name: \"Salesforce Lightning\",\n skin: enums.eSkin.material,\n background: \"#f7f7f7\",\n input: \"#ffffff\",\n header: \"#16325C\",\n primary: \"#16325C\",\n accent: \"#00A1E0\",\n warn: \"#e33e1c\",\n success: \"#14a54a\",\n border: \"#d8dde6\",\n dark: false,\n font: \"Roboto\",\n fontSize: 15,\n radius: 2\n },\n {\n id: -7,\n name: \"Classic\",\n skin: enums.eSkin.material,\n background: \"#f2f2f2\",\n input: \"#FFFFFF\",\n header: \"#084860\",\n primary: \"#084860\",\n accent: \"#E3831C\",\n warn: \"#E33E1C\",\n success: \"#14A54A\",\n border: \"#CCC\",\n dark: false,\n font: \"Roboto\",\n fontSize: 15,\n radius: 4\n },\n ];\n var queryString = $location.search();\n this.loadTemplate().then(function () {\n _this.parseAndLoad(_this.getActiveTheme());\n });\n $transitions.onFinish({}, function (transition) {\n var from = transition.from().name;\n var to = transition.to().name;\n if ((to == \"sceneEdit\" && from != \"sceneEdit\") || from == \"sceneEdit\" && to != \"sceneEdit\") {\n _this.parseAndLoad(_this.getActiveTheme());\n }\n });\n }\n ThemeService.prototype.loadTemplate = function () {\n var _this = this;\n // in debug, we get the css from the server so that it can be changed without stopping debugging\n if (this.$rootScope.clusterEnv == enums.eClusterEnv.dev) {\n return this.$http.get(\"kbmax-theme.css\").then(function (r) {\n return _this.themeCss = r.data;\n });\n }\n else {\n this.themeCss = this.$rootScope.context.themeCss;\n return new _rules.KPromise(this.themeCss);\n }\n };\n ThemeService.prototype.getDefaultTheme = function (id) {\n if (id === void 0) { id = null; }\n return this.defaultThemes.find(function (t) { return t.id == id; });\n };\n ThemeService.prototype.getActiveTheme = function () {\n var _a;\n var queryString = this.$location.search();\n if (queryString[\"idtheme\"] && !this.$rootScope.context.sfdcCanvasRequest) {\n var idTheme = Number(queryString[\"idtheme\"]);\n if (idTheme > 0) {\n return this.$rootScope.context.theme;\n }\n else {\n return this.getDefaultTheme(idTheme);\n }\n }\n else if (this.$rootScope.context.sfdcCanvasRequest) {\n var sfTheme = this.getDefaultTheme(-6);\n //if they have a non-default theme setup, then we use the skin from that. This way they get the salesforce theme,\n //but with the skin they want (material or classic)\n if (this.$rootScope.companySettings.idTheme && this.$rootScope.companySettings.idTheme > 0) {\n sfTheme.skin = this.$rootScope.context.theme.skin;\n }\n //let overrideTheme = await this.$apiService.themes.getById(1);\n //sfTheme = overrideTheme;\n if (queryString['idtheme']) {\n return (_a = this.$rootScope.context.theme) !== null && _a !== void 0 ? _a : sfTheme;\n }\n console.log(sfTheme);\n return sfTheme;\n }\n else if ((this.$state.current && this.$state.current.name == \"sceneEdit\" && !this.$state.transition)\n || (this.$state.transition && (this.$state.transition.to().name == \"sceneEdit\"))) {\n return this.getDefaultTheme(-1);\n }\n else if (this.$rootScope.context.theme) {\n return this.$rootScope.context.theme;\n }\n else {\n return this.getDefaultTheme(this.$rootScope.companySettings.idTheme);\n }\n };\n ThemeService.prototype.getRgbString = function (theme, palette, shade, opacity, contrast, grayscale) {\n var c = new _tools.Color(theme[palette]);\n var offset = shade - 50;\n if (theme.dark)\n offset = -offset;\n var percent = Math.abs(offset / 2);\n if (offset > 0) {\n c = _tools.Color.darken(c.getOriginalInput(), percent);\n }\n else if (offset < 0) {\n c = _tools.Color.lighten(c.getOriginalInput(), percent);\n }\n if (contrast) {\n if (c.isDark()) {\n c = new _tools.Color({ r: 250, g: 250, b: 250 });\n }\n else {\n c = new _tools.Color({ r: 17, g: 17, b: 17 });\n }\n }\n if (grayscale) {\n var hsv = c.toHsv();\n hsv.s = 0;\n c = new _tools.Color(hsv);\n }\n c.setAlpha(opacity);\n return c.toRgbString();\n };\n ThemeService.prototype.parseTheme = function (theme) {\n var _this = this;\n theme = theme || this.getDefaultTheme();\n var hueRegex = new RegExp(\n // tslint:disable-next-line:max-line-length\n '(\\'|\")?{{\\\\s*(background|input|primary|accent|warn|success|border|header)_(color|contrast|grayscale)_?(\\\\d\\\\.?\\\\d*)?_?(\\\\d\\\\.?\\\\d*)?\\\\s*}}(\\\"|\\')?', \"g\");\n var css = this.themeCss.replace(hueRegex, function (match, quotes, palette, cType, shade, opacity) {\n var shadeNum = shade ? Number(shade) : 50;\n var opacityNum = opacity == null ? 1 : Number(opacity) / 100;\n return _this.getRgbString(theme, palette, shadeNum, opacityNum, (cType == \"contrast\"), (cType == \"grayscale\"));\n });\n // border-radius\n css = css.replaceAll(\"'{{radius}}'\", theme.radius + \"px\");\n css = css.replaceAll(\"'{{fontSize}}'\", theme.fontSize + \"px\");\n // font\n if (theme.font) {\n css = css.replaceAll(\"{{font}}\", theme.font);\n }\n if (theme.customFontUrl) {\n css = \"@import url('\".concat(theme.customFontUrl, \"');\\n\") + css;\n }\n return css;\n };\n ThemeService.prototype.setThemeToHead = function (themeCss) {\n var style = document.getElementById(\"kbmax-theme\");\n if (!style) {\n style = document.createElement(\"style\");\n style.id = \"kbmax-theme\";\n }\n style.type = \"text/css\";\n style.innerHTML = themeCss;\n if (!style.parentElement) {\n document.head.appendChild(style);\n }\n };\n ThemeService.prototype.refreshActiveTheme = function () {\n this.parseAndLoad(this.getActiveTheme());\n };\n ThemeService.prototype.parseAndLoad = function (theme) {\n var css = this.parseTheme(theme);\n this.setThemeToHead(css);\n this.$rootScope.currentTheme = theme;\n };\n ThemeService = __decorate([\n NgService({\n token: Token.ThemeService,\n dependencies: [\n Token.$RootScope,\n Token.$Http,\n Token.$Location,\n Token.$Transitions,\n Token.$State\n ]\n })\n ], ThemeService);\n return ThemeService;\n }());\n\n var UploadService = /** @class */ (function () {\n function UploadService($q, $http, $rootScope) {\n this.$q = $q;\n this.$http = $http;\n this.$rootScope = $rootScope;\n this.uploadInputHelper = angular.element('');\n }\n UploadService.prototype.promptUserToChooseFile = function (accept) {\n var _this = this;\n var deferred = this.$q.defer();\n this.uploadInputHelper = angular.element('');\n if (this.currentCallback)\n this.uploadInputHelper.unbind(\"change\", this.currentCallback);\n this.uploadInputHelper.val(null); //clear the value otherwise the change event won't fire if another file is picked\n if (accept) {\n this.uploadInputHelper.attr(\"accept\", accept);\n }\n else {\n this.uploadInputHelper.removeAttr(\"accept\");\n }\n this.currentCallback = function (e) {\n var element = e.target;\n _this.uploadInputHelper[0].removeEventListener(\"change\", _this.currentCallback);\n _this.currentCallback = null;\n if (!element || element.files.length == 0) {\n deferred.reject();\n return;\n }\n var file = element.files[0];\n file.fullPath = _this.uploadInputHelper.val();\n deferred.resolve(file);\n };\n this.uploadInputHelper[0].addEventListener(\"change\", this.currentCallback);\n this.uploadInputHelper[0].click();\n return deferred.promise;\n };\n UploadService.prototype.promptUserToChooseFiles = function () {\n var _this = this;\n var deferred = this.$q.defer();\n this.uploadInputHelper = angular.element('');\n this.uploadInputHelper.attr(\"multiple\", \"multiple\");\n if (this.currentCallback)\n this.uploadInputHelper.unbind(\"change\", this.currentCallback);\n this.uploadInputHelper.val(null); //clear the value otherwise the change event won't fire if another file is picked\n this.currentCallback = function (e) {\n _this.uploadInputHelper.removeAttr(\"multiple\");\n var element = e.target;\n _this.uploadInputHelper.unbind(\"change\", _this.currentCallback);\n _this.currentCallback = null;\n if (!element || element.files.length == 0) {\n deferred.reject();\n return;\n }\n var val = _this.uploadInputHelper.val();\n var files = [];\n for (var _i = 0, _a = element.files; _i < _a.length; _i++) {\n var f = _a[_i];\n f.fullPath = val;\n files.push(f);\n }\n deferred.resolve(files);\n };\n this.uploadInputHelper.bind(\"change\", this.currentCallback);\n this.uploadInputHelper.click();\n return deferred.promise;\n };\n UploadService.prototype.uploadAttachment = function (file, entity, url) {\n var postConfig = {\n // add this to not serialize form data\n transformRequest: angular.identity,\n // set header to undefined so the browser sets the multipart content type\n headers: { \"Content-Type\": undefined }\n };\n var deferred = this.$q.defer();\n var formData = new FormData();\n formData.append(\"file\", file);\n formData.append(\"json\", JSON.stringify(entity));\n this.$http.post(url, formData, postConfig).then(function (response) {\n // returns the filename of the new node in the upload scene\n var uploadResult = response.data;\n deferred.resolve(uploadResult);\n }, function (reason) {\n deferred.reject(reason);\n });\n return deferred.promise;\n };\n UploadService.prototype.uploadFileToMedia = function (file, dir, apiPath) {\n if (apiPath === void 0) { apiPath = \"api/media\"; }\n var d = this.$q.defer();\n var xhr = new XMLHttpRequest();\n var formData = new FormData();\n formData.append(\"file\", file);\n formData.append(\"dir\", dir);\n xhr.onreadystatechange = (function (e) {\n if (xhr.readyState == 4) {\n if (xhr.status == 200) {\n d.resolve();\n }\n else {\n d.reject();\n }\n }\n });\n // xhr.upload.onload = d.resolve;\n xhr.upload.onprogress = d.notify;\n // xhr.addEventListener(\"error\", d.reject);\n xhr.addEventListener(\"abort\", d.reject, false);\n xhr.open(\"POST\", apiPath + \"/upload\", true);\n // xhr.setRequestHeader(\"Content-Type\", \"multipart/form-data\");\n // xhr.setRequestHeader(\"x-ms-version\", \"2014-02-14\");\n // xhr.setRequestHeader(\"x-ms-date\",(new Date()).toISOString());\n // TODO: kbmax3dev is hardcoded. Need a way to determine the correct account to use (maybe Web.config?)\n // xhr.setRequestHeader(\"Authentication\", \"SharedKey kbmax3dev:\" + signature);\n // xhr.setRequestHeader(\"x-ms-blob-type\", \"BlockBlob\");\n xhr.send(formData);\n return d.promise;\n };\n UploadService.prototype.uploadProfileImage = function (file, userId) {\n var url = \"/api/users/profileimage\";\n var postConfig = {\n // add this to not serialize form data\n transformRequest: angular.identity,\n // set header to undefined so the browser sets the multipart content type\n headers: { \"Content-Type\": undefined }\n };\n var formData = new FormData();\n formData.append(\"userId\", userId.toString());\n formData.append(\"file\", file, file.name);\n var deferred = this.$q.defer();\n // post the file\n this.$http.put(url, formData, postConfig).then(function (response) {\n // returns the filename of the new node in the upload scene\n var uploadResult = response.data;\n deferred.resolve(uploadResult.filename);\n }, function (reason) {\n deferred.reject(reason);\n });\n return deferred.promise;\n };\n UploadService.prototype.importConfigurator = function (file) {\n var formData = new FormData();\n formData.append(\"file\", file);\n return this.uploadFile(formData, \"api/admin/products/import\");\n };\n UploadService.prototype.uploadConfiguredProductFile = function (file, options) {\n if (options === void 0) { options = { convertPdfToImage: false }; }\n var formData = new FormData();\n formData.append(\"file\", file);\n formData.append(\"convertPdfToImage\", options.convertPdfToImage.toString());\n return this.uploadFile(formData, \"api/quotes/filefromconfiguratorfield\");\n };\n UploadService.prototype.uploadQuoteFile = function (file, options) {\n if (options === void 0) { options = { convertPdfToImage: false }; }\n var formData = new FormData();\n formData.append(\"file\", file);\n formData.append(\"convertPdfToImage\", options.convertPdfToImage.toString());\n return this.uploadFile(formData, \"api/quotes/filefromquoteheaderfield\");\n };\n UploadService.prototype.uploadFile = function (formData, url) {\n var postConfig = {\n // add this to not serialize form data\n transformRequest: angular.identity,\n // set header to undefined so the browser sets the multipart content type\n headers: { \"Content-Type\": undefined },\n tracker: this.$rootScope.contentTracker\n };\n var deferred = this.$q.defer();\n var xhr = new XMLHttpRequest();\n this.$http.post(url, formData, postConfig).then(function (response) {\n // returns the filename of the new node in the upload scene\n var uploadResult = response.data;\n deferred.resolve(uploadResult);\n }, function (reason) {\n deferred.reject(reason);\n });\n return deferred.promise;\n };\n UploadService = __decorate([\n NgService({\n token: Token.UploadService,\n dependencies: [\n Token.$Q,\n Token.$Http,\n Token.$RootScope,\n ]\n })\n ], UploadService);\n return UploadService;\n }());\n\n var BaseController = /** @class */ (function () {\n function BaseController() {\n }\n /**\n * a callback used by ui-router to notify us when query string parameters have been changed.\n * @param changedParams\n * @param $transition$\n */\n BaseController.prototype.uiOnParamsChanged = function (changedParams, $transition$) {\n // do something with the changed params\n // you can inspect $transition$ to see the what triggered the dynamic params change.\n };\n return BaseController;\n }());\n\n var CrudController = /** @class */ (function (_super) {\n __extends(CrudController, _super);\n function CrudController($scope, agg, model) {\n var _this = _super.call(this) || this;\n _this.$scope = $scope;\n _this.agg = agg;\n _this.loadPromises = [];\n _this.deleteMsg = loc.msg_confirmdelete;\n _this.onSocketRelationshipEdited = function (editedId, relationshipName) {\n var callback = _this.relationshipEditedCallbacks[relationshipName];\n if (callback && editedId == _this.$stateParams.id) {\n _this.client(_this.api).getById(editedId).then(function (r) { return callback(r); });\n }\n };\n _this.onSocketDeletedDelegate = function (editedId) {\n if (editedId == _this.$stateParams.id) {\n _this.onSocketDeleted();\n }\n };\n _this.onSocketEditedDelegate = function (editedId) {\n if (editedId == _this.$stateParams.id) {\n _this.onSocketEdited();\n }\n };\n _this.relationshipEditedCallbacks = {};\n _this.$http = agg.$http;\n _this.$stateParams = Object.assign({}, agg.$stateParams); //$stateParams is actually a global object that is changed before $destroy is called, so we create a clone of it so that it's static for the life of this view\n _this.$rootScope = agg.$rootScope;\n _this.$state = agg.$state;\n _this.$window = agg.$window;\n _this.dialogService = agg.dialogService;\n _this.drawerService = agg.drawerService;\n _this.$q = agg.$q;\n _this.signalrService = agg.signalrService;\n _this.api = agg.api;\n _this.$transitions = agg.$transitions;\n setTimeout(function () {\n _this.$q.all(_this.loadPromises).finally(function () {\n _this.markChangesClean();\n });\n });\n var offTransition = _this.$transitions.onStart({}, function (transition) {\n if (_this.bypassUnsavedConfirmation)\n return;\n // When selecting items in the adminBaseController tree, for instance, this call\n // is sometimes made, so we'll check to ensure we're actually navigating out of\n // the page.\n if (transition.from().name == transition.to().name)\n return;\n if (!_this.modelIsClean()) {\n var d_1 = _this.$q.defer();\n _this.dialogService.confirm(loc.msg_confirmunsavedchanges, function () {\n d_1.resolve(true);\n }, function () {\n d_1.resolve(false);\n });\n return d_1.promise;\n }\n return true;\n });\n var onNavigateAway = function (e) {\n if (_this.bypassUnsavedConfirmation)\n return;\n if (!_this.modelIsClean()) {\n // If we haven't been passed the event get the window.event\n e = e || window.event;\n var message = loc.msg_confirmunsavedchanges;\n // For IE6-8 and Firefox prior to version 4\n if (e) {\n e.returnValue = message;\n }\n // For Chrome, Safari, IE8+ and Opera 12+\n return message;\n }\n return null;\n };\n window.onbeforeunload = onNavigateAway;\n var offOnLogin = _this.$rootScope.$on(_tools.events.loginSuccessful, function () {\n _this.subscribe();\n });\n $scope.$on(\"$destroy\", function () {\n window.onbeforeunload = null;\n offTransition();\n offOnLogin();\n _this.unsubscribe();\n });\n $scope.model = model;\n $scope.validation = {};\n // set view variables to make it easy for views to bind to\n if (_this.$state.current.data) {\n $scope.isEdit = (_this.$state.current.data.viewType == enums.eViewType.edit);\n $scope.isNew = (_this.$state.current.data.viewType == enums.eViewType.new);\n $scope.isView = (_this.$state.current.data.viewType == enums.eViewType.view);\n }\n $scope.cancel = function () {\n _this.onCancel();\n _this.bypassUnsavedConfirmation = true;\n _this.$window.history.back();\n _this.unsubscribe();\n };\n $scope.delete = function () {\n return _this.delete();\n };\n $scope.save = function () {\n return _this.save().then(function () {\n _this.markChangesClean();\n });\n };\n _this.handleResponse = function (responseData, responseStatus) {\n $scope.validation = _this.getValidationObject(responseData, responseStatus);\n if ($scope.validation) {\n var alertMsg = $scope.validation.form || loc.msg_formerror;\n _this.dialogService.alert({ type: enums.eAlertType.error, msg: alertMsg });\n }\n else if (responseStatus == 500) {\n _this.dialogService.alert({ type: enums.eAlertType.error, msg: loc.msg_500error });\n }\n };\n _this.subscribe();\n return _this;\n }\n CrudController.prototype.client = function (api) { throw new Error(\"This method is abstract\"); };\n CrudController.prototype.onSuccess = function () { throw new Error(\"This method is abstract\"); };\n CrudController.prototype.onCancel = function () { };\n CrudController.prototype.onDelete = function () { throw new Error(\"crudController.onDelete is abstract\"); };\n CrudController.prototype.webSocketEntityType = function () { return null; };\n CrudController.prototype.waitForRefresh = function () { return false; };\n CrudController.prototype.save = function () {\n if (this.$scope.isEdit) {\n return this.savePut();\n }\n else if (this.$scope.isNew) {\n return this.savePost();\n }\n };\n CrudController.prototype.savePut = function () {\n var _this = this;\n if (!this.isSaving) {\n this.isSaving = true;\n return this.$http.put(\"\".concat(this.client(this.api).baseUrl, \"/\").concat(this.$stateParams.id, \"?waitForRefresh=\").concat(this.waitForRefresh()), this.getModelForSave(), { tracker: this.$rootScope.contentTracker }).then(function (r) {\n _this.setUpdatedModel(r.data);\n _this.onSuccess();\n _this.$scope.$broadcast(\"saveSuccess\", r.data);\n }, function (r) {\n _this.handleResponse(r.data, r.status);\n })\n .finally(function () {\n _this.isSaving = false;\n });\n }\n };\n CrudController.prototype.savePost = function () {\n var _this = this;\n if (!this.isSaving) {\n this.isSaving = true;\n return this.$http.post(\"\".concat(this.client(this.api).baseUrl, \"?waitForRefresh=\").concat(this.waitForRefresh()), this.getModelForSave(), { tracker: this.$rootScope.contentTracker }).then(function (r) {\n _this.setUpdatedModel(r.data);\n _this.onSuccess();\n _this.$scope.$broadcast(\"saveSuccess\", r.data);\n _this.subscribe();\n }, function (r) {\n _this.handleResponse(r.data, r.status);\n })\n .finally(function () {\n _this.isSaving = false;\n });\n }\n };\n CrudController.prototype.delete = function () {\n var _this = this;\n var deferred = this.$q.defer();\n this.dialogService.dialog({\n content: this.deleteMsg,\n buttons: [\n new enums.DialogButton(loc.ok, _tools.icons.success, function (args) {\n _this.unsubscribe(); //unsubscribe before we delete, otherwise we get the notification about the deletion before we've left the state\n _this.client(_this.api).delete(_this.$stateParams.id).then(function () {\n _this.bypassUnsavedConfirmation = true;\n deferred.resolve();\n _this.onDelete();\n });\n }),\n new enums.DialogButton(loc.cancel, _tools.icons.cancel, function (args) {\n deferred.reject();\n })\n ]\n });\n return deferred.promise;\n };\n CrudController.prototype.modelIsClean = function () {\n return angular.equals(this.cleanModel, angular.copy(this.getModelForSave()));\n };\n CrudController.prototype.getModelForSave = function () {\n return this.$scope.model;\n };\n CrudController.prototype.setUpdatedModel = function (model) {\n this.$scope.model = model;\n };\n CrudController.prototype.markChangesClean = function () {\n this.cleanModel = angular.copy(this.getModelForSave());\n };\n CrudController.prototype.getValidationObject = function (responseData, responseStatus) {\n var o;\n if (responseStatus == 400) {\n o = {};\n var _loop_1 = function (prop) {\n // ignore the json type property\n if (prop !== \"$type\") {\n var newProp = prop === \"\" ? \"form\" : prop;\n var sections_1 = newProp.split(\".\");\n sections_1.forEach(function (section, key) {\n sections_1[key] = section.toCamelCase();\n });\n newProp = sections_1.join(\".\");\n o[newProp] = responseData[prop].join(\"\\n\");\n }\n };\n for (var prop in responseData) {\n _loop_1(prop);\n }\n }\n return o;\n };\n /**\n * called when the entity has been deleted. Can be overriden for custom behavior\n * @param editedId\n */\n CrudController.prototype.onSocketDeleted = function () {\n var _this = this;\n this.dialogService.alert({\n type: enums.eAlertType.error,\n msg: \"Sorry. This entity has just been deleted by another user.\"\n });\n setTimeout(function () { _this.onDelete(); }, 1000);\n };\n /**\n * called when the entity has been edited by another consumer. Can be overriden for custom behavior.\n * @param editedId\n */\n CrudController.prototype.onSocketEdited = function () {\n var _this = this;\n this.client(this.api).getById(this.$stateParams.id).then(function (r) {\n _this.setUpdatedModel(r);\n });\n };\n CrudController.prototype.subscribe = function () {\n this.unsubscribe();\n var entityType = this.webSocketEntityType();\n if (!entityType || !this.$stateParams.id)\n return;\n this.signalrService.invoke(\"subscribe\", this.$rootScope.company.uniqueName, entityType, this.$stateParams.id);\n this.signalrService.on(\"edited\", this.onSocketEditedDelegate);\n this.signalrService.on(\"deleted\", this.onSocketDeletedDelegate);\n this.signalrService.on(\"relationshipEdited\", this.onSocketRelationshipEdited);\n };\n CrudController.prototype.unsubscribe = function () {\n // console.log(\"Unsubscribing...\");\n var entityType = this.webSocketEntityType();\n if (!entityType || !this.$stateParams.id)\n return;\n this.signalrService.invoke(\"unsubscribe\", this.$rootScope.company.uniqueName, entityType, this.$stateParams.id);\n this.signalrService.off(\"edited\", this.onSocketEditedDelegate);\n this.signalrService.off(\"deleted\", this.onSocketDeletedDelegate);\n this.signalrService.off(\"relationshipEdited\", this.onSocketRelationshipEdited);\n };\n CrudController.prototype.onRelationshipEdited = function (property, callback) {\n this.relationshipEditedCallbacks[property] = callback;\n };\n CrudController = __decorate([\n NgView({\n token: Token.CrudView,\n dependencies: [\n Token.$Scope,\n Token.CrudService,\n Token.Model\n ],\n resolves: [\n {\n name: \"model\",\n dependencies: [\n Token.$StateParams,\n Token.AuthService,\n Token.$RootScope,\n Token.ApiService\n ],\n // tslint:disable-next-line:object-literal-shorthand\n fn: function (// need to use \"function\" instead of arrow here because we use \"this\" to get the api client\n $stateParams, authService, $rootScope, api) {\n var constructor = this;\n // would like to check the state here to get the view type, \n // but there is a bug that is sending the old state: \n // https://github.com/angular-ui/ui-router/issues/238\n // instead we'll look for the id state parameter, which shouldn't be there for the new screens\n if ($stateParams.id) {\n return authService.authPromise.then(function () {\n return constructor.prototype.client(api).getById($stateParams.id, $rootScope.contentTracker);\n });\n }\n else {\n return authService.authPromise;\n }\n }\n }\n ]\n })\n ], CrudController);\n return CrudController;\n }(BaseController));\n\n var ContactController = /** @class */ (function (_super) {\n __extends(ContactController, _super);\n function ContactController($scope, crudService, model) {\n var _this = _super.call(this, $scope, crudService, model) || this;\n _this.$scope = $scope;\n _this.drawerService.setHelpUrl(\"Contacts\");\n var viewType = _this.$state.current.data.viewType;\n if ($scope.model) {\n _this.deleteMsg = loc.msg_deleterecord.format(loc.contact_title, $scope.model.firstName + \" \" + $scope.model.lastName);\n }\n if (viewType == enums.eViewType.new) {\n $scope.model = {\n idCompany: _this.$rootScope.company.id,\n shipToBillingAddress: true\n };\n }\n // customers\n _this.$http.get(\"/api/customers/selections\").then(function (response) { return $scope.customers = response.data; });\n // add drawers\n if ($scope.isEdit || $scope.isNew) {\n var drDelete = _this.drawerService.addDrawer(_tools.icons.deleter, loc.deleter, $scope.delete, $scope.isEdit);\n var drSave = _this.drawerService.addDrawer(_tools.icons.save, loc.save, $scope.save);\n var drCancel = _this.drawerService.addDrawer(_tools.icons.cancel, loc.cancel, $scope.cancel);\n }\n else {\n var drEdit = _this.drawerService.addDrawer(_tools.icons.edit, loc.edit, function () {\n _this.$state.go(\"kb.admin.contactEdit\", { id: $scope.model.id });\n }, _this.$rootScope.user.canModifyCustomers);\n var drDelete = _this.drawerService.addDrawer(_tools.icons.deleter, loc.deleter, $scope.delete, _this.$rootScope.user.canModifyCustomers);\n }\n return _this;\n }\n ContactController.prototype.client = function (api) {\n return api.contacts;\n };\n ContactController.prototype.waitForRefresh = function () {\n return true;\n };\n ContactController.prototype.onSuccess = function () {\n this.$state.go(\"kb.contacts\");\n };\n ContactController.prototype.onDelete = function () {\n this.$state.go(\"kb.contacts\");\n };\n ContactController = __decorate([\n NgView({\n token: Token.ContactView,\n inherit: [Token.CrudView]\n })\n ], ContactController);\n return ContactController;\n }(CrudController));\n\n /**\n * base class for handling search pages.\n */\n var SearchController = /** @class */ (function (_super) {\n __extends(SearchController, _super);\n function SearchController($scope, agg, bypassInit //for derived classes (like products view) that need to explicitly call init to have a chance to fill in other scope items first\n ) {\n if (bypassInit === void 0) { bypassInit = false; }\n var _this = _super.call(this) || this;\n _this.$scope = $scope;\n _this.agg = agg;\n _this.bypassInit = bypassInit;\n _this.pageSize = document.body.clientHeight > 1130 ? 42 : 22;\n _this.epoch = null;\n _this.filledFilterSources = [];\n $scope.drawerService = agg.drawerService;\n $scope.binding = { selected: null, search: null };\n $scope.results = [];\n $scope.savedSearchEnabled = false; //disabled by default. Derived controllers can override\n $scope.allowSearch = true;\n $scope.query = function (append) {\n if (append === void 0) { append = false; }\n var filters = []\n .concat($scope.binding.search.enabled ? $scope.binding.search.filters : [])\n .concat(_this.getExtraFilters());\n if (append && _this.epoch) {\n //if we are appending to the infinite scroll, use the epoch as a filter so that we don't get duplicates\n filters.push({\n property: \"createdDate\",\n control: enums.eFilterControl.dateRange,\n type: enums.eFilterType.property,\n max: _this.epoch\n });\n }\n if (!_this.epoch) {\n _this.epoch = new Date();\n }\n _this.postProcessFilters(filters);\n var sortInfo = _this.getSortInfo();\n var args = {\n skip: append ? $scope.results.length : 0,\n take: _this.pageSize,\n fields: _this.fields(),\n query: $scope.binding.search.query,\n sortField: sortInfo.sortField,\n descending: sortInfo.descending,\n filters: filters,\n nestedPath: _this.getNestedPath(),\n nestedFields: _this.nestedFields()\n };\n var tracker = append ? agg.$rootScope.infiniteScrollTracker : agg.$rootScope.contentTracker;\n return _this.searchCall(args, tracker).then(function (r) {\n _this.massageResults(r);\n append ? $scope.results.pushArray(r) : $scope.results = r;\n return r;\n });\n };\n $scope.suggestValueField = \"name\";\n $scope.suggest = function (query) {\n if (query) {\n return _this.client(agg.api).suggest({ query: query, fields: [$scope.suggestValueField] });\n }\n };\n $scope.addFilter = function (f) {\n var newFilter = JSON.parse(JSON.stringify(f));\n $scope.binding.search.filters.push(newFilter);\n _this.fillFilters();\n };\n $scope.removeFilter = function (f) {\n $scope.binding.search.filters.remove(f);\n // $scope.availableFilters.push(f);\n f.values = (f.control == enums.eFilterControl.multiSelect ? [] : [null]);\n $scope.reload();\n };\n $scope.toggleFilters = function () {\n $scope.binding.search.enabled = !$scope.binding.search.enabled;\n $scope.reload();\n };\n $scope.sort = function (sortColumn) {\n if (sortColumn.sortable) {\n $scope.columns.forEach(function (col) {\n if (col.field != sortColumn.field) {\n col.sorted = false;\n col.descending = false;\n }\n else {\n if (!col.sorted) {\n col.sorted = true;\n col.descending = false;\n }\n else {\n if (col.descending) {\n col.sorted = false;\n col.descending = false;\n }\n else {\n col.sorted = true;\n col.descending = true;\n }\n }\n if (col.sorted) {\n $scope.binding.search.sortField = col.field;\n $scope.binding.search.descending = col.descending;\n }\n else {\n $scope.binding.search.sortField = null;\n $scope.binding.search.descending = false;\n }\n }\n });\n lastLength = 0;\n lastRetrieved = 0;\n $scope.reload();\n }\n };\n $scope.modelTypeChange = function (modelType) {\n agg.$state.go(modelType.state);\n };\n var lastLength = 0;\n var lastRetrieved = -1;\n $scope.infiniteScroll = function () {\n // if the list doesn't have at least the page size of items, it means there's no more\n // available, so no need to do another page\n var count = $scope.results.length;\n lastRetrieved = count == 0 ? -1 : count - lastLength;\n var noMore = count > 0 && (count % _this.pageSize != 0);\n if (!noMore && (lastRetrieved < 0 || lastRetrieved == _this.pageSize)) {\n lastLength = count;\n return $scope.query(true);\n }\n };\n $scope.reload = function (force) {\n if (force === void 0) { force = false; }\n var search = _this.$scope.binding.search;\n var params = _this.getQueryStringParams() || {};\n if (search.enabled) {\n params = Object.assign(params, { search: agg.base64Service.encode(JSON.stringify(search)) });\n }\n else {\n //create a search without filters\n var basicSearch = __assign(__assign({}, search), { filters: [] });\n params = Object.assign(params, { search: agg.base64Service.encode(JSON.stringify(basicSearch)) });\n }\n var options = {};\n if (force)\n options.reload = true;\n _this.epoch = null;\n agg.$state.go(agg.$state.current.name, params, options);\n };\n // set all filter sources to an empty array so we have a reference to bind to\n $scope.filterSource = {};\n for (var p in enums.eFilterSource)\n $scope.filterSource[p] = [];\n _this.filterSourceInfo = {};\n for (var e in enums.eFilterSource)\n _this.filterSourceInfo[e] = { valueField: \"id\", labelField: \"name\" };\n _this.filterSourceInfo[enums.eFilterSource.states] = { valueField: \"value\", labelField: \"label\" };\n _this.filterSourceInfo[enums.eFilterSource.roles] = { valueField: \"id\", labelField: \"role\" };\n _this.filterSourceInfo[enums.eFilterSource.manufacturers] = { valueField: null, labelField: null };\n _this.filterSourceInfo[enums.eFilterSource.enum] = { valueField: \"value\", labelField: \"name\" };\n $scope.editSearch = function (search) {\n _this.saveSearchDialog(search);\n };\n $scope.deleteSearch = function (s) {\n return agg.api.savedSearches.delete(s.id)\n .then(function () { return $scope.savedSearches.removeWhere(function (search) { return search.id == s.id; }); });\n };\n $scope.canDeleteSearch = function (s) {\n return _this.agg.$rootScope.user.isCompanyAdmin ||\n _this.agg.$rootScope.user.isAdmin ||\n s.createdBy == _this.agg.$rootScope.user.id;\n };\n $scope.$watch(\"binding.selected\", function (newVal, oldVal) {\n if (newVal != oldVal) {\n $scope.binding.search = $scope.binding.selected;\n //filters need to be re-filled because they are missing $key in saved searches\n _this.fillFilters();\n $scope.reload();\n }\n });\n if (!bypassInit) {\n _this.init();\n }\n return _this;\n }\n /** derived classes must call init. This gives derives classes a chance to fill in scope, etc before things are processed */\n SearchController.prototype.init = function () {\n /**\n * could be called in the following ways:\n * -no query string: create a new savedSearch and fill it with defaults\n * -#search=[base64 encoded json string of the search]\n * -#searchId=[the id of the saved search] : call the server with the saved search id\n */\n if (this.agg.$state.params.search) {\n this.$scope.binding.search = JSON.parse(this.agg.base64Service.decode(this.agg.$state.params.search));\n this.loadedFromQueryString(this.$scope.binding.search);\n }\n else {\n this.$scope.binding.search = this.newSearch();\n }\n this.$scope.availableFilters = this.getFiltersFromMeta(this.$scope.binding.search.modelType);\n this.$scope.availableFilters.sortBy(function (f) { return f.label; });\n this.fillFilters();\n this.refreshSavedSearches();\n };\n SearchController.prototype.client = function (api) {\n throw new Error(\"client() is abstract\");\n };\n /**can be overridden to customize the actual call to search api */\n SearchController.prototype.searchCall = function (args, tracker) {\n return this.client(this.agg.api).search(args, tracker);\n };\n /**can be overriden to catch when we have just loaded a search via the query string */\n SearchController.prototype.loadedFromQueryString = function (search) {\n };\n /**can be overriden by derived class to provide extra query string params */\n SearchController.prototype.getQueryStringParams = function () {\n return {};\n };\n /**\n * the properties of the queried object that should be returned.\n */\n SearchController.prototype.fields = function () {\n return this.getFieldsFromMeta(this.$scope.binding.search.modelType);\n };\n /**\n * a new fresh search. Can be overriden by the derived controller\n */\n SearchController.prototype.newSearch = function () {\n return {\n filters: [],\n roles: []\n };\n };\n /** can be overridden by derived class to massage the results before showing them on the screen */\n SearchController.prototype.massageResults = function (items) {\n };\n /**\n * can be overridden by derived controllers to add a raw filter to the search\n */\n SearchController.prototype.getExtraFilters = function () {\n return [];\n };\n /**\n * can be overriden by derived controllers to give an extra flag about what we're\n * searching (like configured products needs to be set to \"products\" so that the\n * search repo knows what we're doing)\n */\n SearchController.prototype.getNestedPath = function () {\n return null;\n };\n /**\n * can be overriden by derived controllers to give relative paths to the properties\n * of the object described in the nestedPath\n */\n SearchController.prototype.nestedFields = function () {\n return [];\n };\n SearchController.prototype.postProcessFilters = function (filters) {\n var _this = this;\n filters.forEach(function (f) {\n if (f.type == enums.eFilterType.attribute) {\n var productsScope = _this.$scope;\n if (productsScope.attributeDb) {\n var att = productsScope.attributeDb[f.attributeId];\n if (att) {\n if (att.type == enums.eAttributeType.number && att.useRangeBuckets) {\n if (f.values && f.values.length && f.values[0] != null) {\n f.min = f.values[0][\"from\"];\n f.max = f.values[0][\"to\"];\n }\n }\n }\n }\n }\n });\n };\n SearchController.prototype.getSortInfo = function () {\n var ret = { sortField: this.$scope.binding.search.sortField, descending: this.$scope.binding.search.descending };\n //calculate sort\n var s = this.$scope.binding.search;\n if (s.enabled) {\n var sortFilter = s.filters.find(function (f) { return f.type == enums.eFilterType.sort; });\n if (sortFilter && sortFilter.values != null && sortFilter.values.length > 0 && sortFilter.values[0]) {\n if (sortFilter.sourceType == enums.eFilterSource.productSorts) {\n var v = sortFilter.values[0];\n if (v.equalsAny(enums.eProductSortBy.relevance, enums.eProductSortBy.popularity)) {\n ret.sortField = \"score\";\n ret.descending = true;\n }\n else if (v == enums.eProductSortBy.priceLowToHigh) {\n ret.sortField = \"price\";\n ret.descending = false;\n }\n else if (v == enums.eProductSortBy.priceHighToLow) {\n ret.sortField = \"price\";\n ret.descending = true;\n }\n else if (v == enums.eProductSortBy.nameAtoZ) {\n ret.sortField = \"name\";\n ret.descending = false;\n }\n }\n }\n }\n return ret;\n };\n SearchController.prototype.getFieldsFromMeta = function (modelType) {\n var m = enums.meta[modelType];\n var fields = [];\n var _loop_1 = function (prop) {\n if (prop[0] != \"$\") {\n var info_1 = m[prop];\n if (info_1.type.endsWith(\"[]\")) {\n // we look at the array type and get it's meta props\n var subFields = this_1.getFieldsFromMeta(info_1.type.substr(0, info_1.type.length - 2));\n subFields.forEach(function (sf) { return fields.push(info_1.name + \".\" + sf); });\n }\n else {\n fields.push(info_1.name);\n }\n }\n };\n var this_1 = this;\n for (var prop in m) {\n _loop_1(prop);\n }\n return fields;\n };\n SearchController.prototype.getFiltersFromMeta = function (modelType, onlyDefaults) {\n var _this = this;\n var m = enums.meta[modelType];\n var filters = [];\n for (var prop in m) {\n if (prop[0] != \"$\") {\n var info = m[prop];\n if (!info.permissions ||\n !info.permissions.length ||\n info.permissions.every(function (p) { return _this.agg.$rootScope.user[\"can\" + p.toPascalCase()]; })) { // check if the current user has permissions to see this filter\n if (!info.type.endsWith(\"[]\") &&\n info.control != enums.eFilterControl.none &&\n (info.default || !onlyDefaults)) {\n filters.push({\n label: loc[\"generic_\" + info.name.toLowerCase() + \"_title\"] ||\n loc[m.$name.toLowerCase() + \"_\" + info.name.toLowerCase() + \"_title\"] ||\n info.name.toPascalCase(),\n type: enums.eFilterType.property,\n property: info.name,\n sourceType: info.source,\n enumType: info.enumType,\n control: info.control,\n valueField: this.filterSourceInfo[info.source].valueField,\n labelField: this.filterSourceInfo[info.source].labelField,\n headerField: this.filterSourceInfo[info.source].labelField,\n values: (info.control == enums.eFilterControl.multiSelect ? [] : [null]),\n sticky: info.sticky\n });\n }\n }\n }\n }\n return filters;\n };\n SearchController.prototype.getFilterKey = function (f) {\n var key = f.sourceType;\n if (f.attributeId) {\n var productsScope = this.$scope;\n key = f.sourceType + \"_\" + f.attributeId + \"_\" + productsScope.binding.selectedCategory.id;\n }\n else if (f.sourceType == enums.eFilterSource.enum) {\n key = f.sourceType + \"_\" + f.enumType;\n }\n return key;\n };\n SearchController.prototype.fillFilters = function () {\n var _this = this;\n this.$scope.binding.search.filters.forEach(function (f) {\n var key = _this.getFilterKey(f);\n f[\"$key\"] = key;\n if (!_this.filledFilterSources.some(function (s) { return s.isEqual(key); })) {\n _this.filledFilterSources.push(key);\n if (f.sourceType == enums.eFilterSource.enum) {\n _this.$scope.filterSource[key] = _this.agg.$filter(\"enum\")(f.enumType, false);\n if (f.enumType == \"eJobStatus\") { // job status is stored as an int in the database\n var i = 0;\n for (var _i = 0, _a = _this.$scope.filterSource[key]; _i < _a.length; _i++) {\n var v = _a[_i];\n v.value = i;\n i++;\n }\n }\n }\n else if (f.sourceType == enums.eFilterSource.users) {\n _this.agg.api.users.search({\n fields: [\"id\", \"firstName\", \"lastName\", \"name\"], sortField: \"firstName\"\n }).then(function (users) { return _this.$scope.filterSource[key] = users; });\n }\n else if (f.sourceType == enums.eFilterSource.states) {\n _this.agg.api.workflows.states()\n .then(function (r) { return _this.$scope.filterSource[key] = __spreadArray([\n { value: null, label: loc.unsubmitted }\n ], r, true); });\n }\n else if (f.sourceType == enums.eFilterSource.properties) {\n _this.$scope.filterSource[key] = Object.keys(enums.meta[_this.$scope.binding.search.modelType + \"Meta\"]);\n }\n else if (f.sourceType == enums.eFilterSource.customers) {\n _this.$scope.filterSource[key] = _this.agg.api.customers\n .search({ fields: [\"id\", \"name\"] })\n .then(function (customers) { return _this.$scope.filterSource[key] = __spreadArray([\n { id: null, name: loc.none.capitalize() }\n ], customers, true); });\n }\n else if (f.sourceType == enums.eFilterSource.configurators) {\n // only get the products this user has the rights to see\n _this.$scope.filterSource[key] = _this.agg.api.products\n .searchByCategory({\n sortField: \"name\",\n fields: [\"id\", \"name\"],\n descending: false,\n filters: [ProductClient.getIsConfiguredFilter(true)],\n take: 500\n })\n .then(function (configs) { return _this.$scope.filterSource[key] = __spreadArray([\n {\n id: null,\n name: loc.any\n }\n ], configs, true); });\n }\n else if (f.sourceType == enums.eFilterSource.roles) {\n _this.$scope.filterSource[key] = _this.agg.api.roles\n .search({ fields: [\"id\", \"role\"] })\n .then(function (roles) { return _this.$scope.filterSource[key] = roles; });\n }\n else if (f.sourceType == enums.eFilterSource.manufacturers) {\n _this.$scope.filterSource[key] = _this.agg.api.products.uniqueValues({ property: enums.meta.Product.manufacturer.name })\n .then(function (manufacturers) { return _this.$scope.filterSource[key] = manufacturers; });\n }\n else if (f.sourceType == enums.eFilterSource.suggestQuotes) {\n _this.$scope.filterSource[key] = function (q) { return _this.agg.api.quotes.suggest({ query: q, fields: [\"name\"] }); };\n }\n else if (f.sourceType == enums.eFilterSource.suggestContacts) {\n _this.$scope.filterSource[key] = function (q) { return _this.agg.api.contacts.suggest({ query: q, fields: [\"name\"] }); };\n }\n else if (f.sourceType == enums.eFilterSource.suggestCustomers) {\n _this.$scope.filterSource[key] = function (q) { return _this.agg.api.customers.suggest({ query: q, fields: [\"name\"] }); };\n }\n else if (f.sourceType == enums.eFilterSource.suggestProducts) {\n _this.$scope.filterSource[key] = function (q) { return _this.agg.api.products.suggest({ query: q, fields: [\"name\"] }); };\n }\n else if (f.sourceType == enums.eFilterSource.productSorts) {\n _this.$scope.filterSource[key] = [\n {\n value: enums.eProductSortBy.relevance,\n label: loc.eproductsortby_relevance_title\n }, {\n value: enums.eProductSortBy.priceLowToHigh,\n label: loc.eproductsortby_pricelowtohigh_title\n }, {\n value: enums.eProductSortBy.priceHighToLow,\n label: loc.eproductsortby_pricehightolow_title\n }, {\n value: enums.eProductSortBy.popularity,\n label: loc.eproductsortby_popularity_title\n }, {\n value: enums.eProductSortBy.nameAtoZ,\n label: loc.eproductsortby_nameatoz_title\n }\n ];\n }\n else if (f.sourceType == enums.eFilterSource.attributes) {\n var productsScope = _this.$scope;\n var categoryIds = [];\n if (productsScope.binding.selectedCategory.id >= 0) {\n categoryIds = productsScope.getChildCategories(productsScope.binding.selectedCategory);\n }\n _this.$scope.filterSource[key] = [];\n if (productsScope.attributeDb) {\n var att_1 = productsScope.attributeDb[f.attributeId];\n if (att_1.type == enums.eAttributeType.number && att_1.useRangeBuckets) {\n _this.agg.api.products.attributeRanges({ id: att_1.id, ranges: att_1.ranges, categoryIds: categoryIds })\n .then(function (buckets) {\n var _a;\n buckets.removeWhere(function (b) { return b.count <= 0; });\n var options = [];\n buckets.forEach(function (b) {\n var label = '';\n if (b.from == null)\n label += \"< \";\n if (b.to == null)\n label += \"> \";\n if (b.from != null)\n label += b.from.toString();\n if (b.from != null && b.to != null)\n label += \" - \";\n if (b.to != null)\n label += b.to.toString();\n options.push({ value: b, label: label });\n });\n (_a = _this.$scope.filterSource[key]).push.apply(_a, options);\n });\n }\n else {\n _this.agg.api.products.uniqueAttributeValues({ id: att_1.id, type: att_1.type, categoryIds: categoryIds })\n .then(function (vals) {\n var _a;\n (_a = _this.$scope.filterSource[key]).push.apply(_a, vals);\n //if we are confined to a list, merge with the category attribute options so we can get the images\n if (att_1.confineToList) {\n var _loop_2 = function (v) {\n var o = att_1.options.find(function (n) { return n.value == v.value; });\n if (o) {\n v[\"image\"] = o.image;\n }\n };\n for (var _i = 0, vals_1 = vals; _i < vals_1.length; _i++) {\n var v = vals_1[_i];\n _loop_2(v);\n }\n }\n });\n // if (att.confineToList) {\n // this.$scope.filterSource[key].push(...att.options);\n // } else {\n // this.agg.api.products.uniqueAttributeValues({ id: att.id, type: att.type })\n // .then(vals => this.$scope.filterSource[key].push(...vals));\n // }\n }\n }\n }\n else if (f.sourceType == enums.eFilterSource.headerFields) {\n _this.agg.api.quoteHeaders.searchFields().then(function (r) {\n _this.$scope.filterSource[key] = r;\n });\n }\n }\n });\n };\n SearchController.prototype.uiOnParamsChanged = function (changedParams, $transition$) {\n if ($transition$.options().source == \"url\") {\n if (changedParams.search) {\n this.$scope.binding.search = JSON.parse(this.agg.base64Service.decode(changedParams.search));\n }\n else {\n this.$scope.binding.search = this.newSearch();\n }\n this.fillSorts(this.$scope.binding.search.sortField, this.$scope.binding.search.descending);\n }\n this.$scope.query(false);\n };\n /** can be overriden to handle what happens after items are deleted */\n SearchController.prototype.onItemsDeleted = function (items) {\n };\n SearchController.prototype.deleteItems = function () {\n var _this = this;\n var selected = this.$scope.results.filter(function (i) { return i.$selected; });\n if (selected.length > 0) {\n this.agg.dialogService.dialog({\n content: loc.msg_confirmdelete,\n buttons: [\n new enums.DialogButton(loc.ok, _tools.icons.success, function (args) {\n var tracker = _this.agg.$rootScope.contentTracker;\n var promises = [];\n selected.forEach(function (item) {\n var promise = _this.client(_this.agg.api).delete(item.id, null, true);\n tracker.addPromise(promise);\n promises.push(promise);\n });\n _this.agg.$q.all(promises).then(function () {\n _this.onItemsDeleted(selected);\n }).finally(function () {\n _this.$scope.reload(true);\n });\n }),\n new enums.DialogButton(loc.cancel, _tools.icons.cancel, function (args) { })\n ]\n });\n }\n };\n SearchController.prototype.clone = function () {\n var _this = this;\n var selected = this.$scope.results.filter(function (i) { return i.$selected; });\n var promises = [];\n selected.forEach(function (item) {\n var promise = _this.client(_this.agg.api).clone(item.id);\n _this.agg.$rootScope.contentTracker.addPromise(promise);\n promises.push(promise);\n });\n this.agg.$q.all(promises).then(function () { return _this.$scope.reload(true); });\n };\n SearchController.prototype.refreshSavedSearches = function () {\n var _this = this;\n if (this.$scope.savedSearchEnabled) {\n return this.agg.api.savedSearches.mySearches(this.$scope.binding.search.modelType).then(function (r) { return _this.$scope.savedSearches = r; });\n }\n };\n SearchController.prototype.saveSearchDialog = function (search) {\n var _this = this;\n search = search || this.$scope.binding.search;\n var dscope = this.agg.$rootScope.$new();\n if (this.agg.$rootScope.user.isCompanyAdmin || this.agg.$rootScope.user.isAdmin) {\n this.agg.api.roles.search({ take: 1000, sortField: \"role\" }).then(function (r) { return dscope.roles = r; });\n }\n dscope.model = { name: \"New Search\", roles: search.roles || [] };\n this.agg.dialogService.dialog({\n template: Dirs.view(\"dialog-save-search\"),\n scope: dscope,\n buttons: [\n new enums.DialogButton(loc.ok, _tools.icons.success, function (args) {\n // validate there is a name\n if (!dscope.model.name) {\n dscope.validation.name = \"Name is required\";\n args.close = false;\n return;\n }\n var newSearch = Object.assign({}, search); // create a new search\n newSearch.id = null; // clear out the id so it's treated as an insert\n newSearch.name = dscope.model.name;\n newSearch.roles = dscope.model.roles;\n _this.agg.api.savedSearches.insert(newSearch, _this.agg.$rootScope.contentTracker).then(function (r) {\n _this.refreshSavedSearches().then(function () {\n _this.$scope.binding.selected = _this.$scope.savedSearches.find(function (ss) { return ss.id == r.id; });\n });\n });\n }),\n new enums.DialogButton(loc.close, _tools.icons.cancel, function (args) { })\n ]\n });\n };\n SearchController.prototype.fillSorts = function (sortColumnName, descending) {\n for (var _i = 0, _a = this.$scope.columns; _i < _a.length; _i++) {\n var col = _a[_i];\n if (!sortColumnName || col.field != sortColumnName) {\n col.sorted = false;\n col.descending = false;\n }\n else {\n col.sorted = true;\n col.descending = descending;\n }\n }\n };\n SearchController = __decorate([\n NgView({\n token: Token.SearchView,\n dependencies: [\n Token.$Scope,\n Token.SearchService\n ]\n })\n ], SearchController);\n return SearchController;\n }(BaseController));\n\n var ContactsController = /** @class */ (function (_super) {\n __extends(ContactsController, _super);\n function ContactsController($scope, agg) {\n var _this = _super.call(this, $scope, agg) || this;\n agg.drawerService.pageTitle = loc.contacts;\n agg.drawerService.pageIcon = _tools.icons.user;\n agg.drawerService.setHelpUrl(\"Contacts\");\n if (agg.$rootScope.user.canModifyCustomers) {\n agg.drawerService.addDrawer(_tools.icons.add, loc.add, function () { return agg.$state.go(\"kb.contactNew\"); });\n agg.drawerService.addDrawer(_tools.icons.clone, loc.clone, function () { return _this.clone(); });\n agg.drawerService.addDrawer(_tools.icons.deleter, loc.deleter, function () { return _this.deleteItems(); });\n }\n return _this;\n }\n ContactsController.prototype.client = function (api) {\n return api.contacts;\n };\n ContactsController.prototype.newSearch = function () {\n return {\n modelType: enums.meta.Contact.$name,\n sortField: \"FirstName\",\n descending: false,\n filters: this.getFiltersFromMeta(enums.meta.Contact.$name, true),\n roles: []\n };\n };\n ContactsController = __decorate([\n NgView({\n token: Token.ContactsView,\n inherit: [Token.SearchView]\n })\n ], ContactsController);\n return ContactsController;\n }(SearchController));\n\n var CustomerController = /** @class */ (function (_super) {\n __extends(CustomerController, _super);\n function CustomerController($scope, crudService, model) {\n var _this = _super.call(this, $scope, crudService, model) || this;\n _this.$scope = $scope;\n _this.drawerService.setHelpUrl(\"Customers\");\n var viewType = _this.$state.current.data.viewType;\n if ($scope.model) {\n _this.deleteMsg = loc.msg_deleterecord.format(loc.customer_title, $scope.model.name);\n }\n if (viewType == enums.eViewType.new) {\n $scope.model = {\n idCompany: _this.$rootScope.company.id,\n name: \"New Customer\",\n shipToBillingAddress: true,\n type: loc.customer_type_direct\n };\n }\n // customerTypes\n _this.$http.get(\"/api/customers/types\").then(function (response) {\n $scope.customerTypes = response.data;\n });\n // add drawers\n if ($scope.isEdit || $scope.isNew) {\n var drDelete = _this.drawerService.addDrawer(_tools.icons.deleter, loc.deleter, $scope.delete, $scope.isEdit);\n var drSave = _this.drawerService.addDrawer(_tools.icons.save, loc.save, $scope.save);\n var drCancel = _this.drawerService.addDrawer(_tools.icons.cancel, loc.cancel, $scope.cancel);\n }\n else {\n var drEdit = _this.drawerService.addDrawer(_tools.icons.edit, loc.edit, function () {\n _this.$state.go(\"kb.admin.customerEdit\", { id: $scope.model.id });\n }, _this.$rootScope.user.canModifyCustomers);\n var drDelete = _this.drawerService.addDrawer(_tools.icons.deleter, loc.deleter, $scope.delete, _this.$rootScope.user.canModifyCustomers);\n }\n return _this;\n }\n CustomerController.prototype.client = function (api) {\n return api.customers;\n };\n CustomerController.prototype.waitForRefresh = function () {\n return true;\n };\n CustomerController.prototype.onSuccess = function () {\n this.$state.go(\"kb.customers\");\n };\n CustomerController.prototype.onDelete = function () {\n this.$state.go(\"kb.customers\");\n };\n CustomerController = __decorate([\n NgView({\n token: Token.CustomerView,\n inherit: [Token.CrudView]\n })\n ], CustomerController);\n return CustomerController;\n }(CrudController));\n\n var CustomersController = /** @class */ (function (_super) {\n __extends(CustomersController, _super);\n function CustomersController($scope, agg) {\n var _this = _super.call(this, $scope, agg) || this;\n agg.drawerService.pageTitle = loc.customers;\n agg.drawerService.pageIcon = _tools.icons.users;\n agg.drawerService.setHelpUrl(\"Customers\");\n if (agg.$rootScope.user.canModifyCustomers) {\n agg.drawerService.addDrawer(_tools.icons.add, loc.add, function () { return agg.$state.go(\"kb.customerNew\"); });\n agg.drawerService.addDrawer(_tools.icons.clone, loc.clone, function () { return _this.clone(); });\n agg.drawerService.addDrawer(_tools.icons.deleter, loc.deleter, function () { return _this.deleteItems(); });\n }\n $scope.fixUrl = function (url) {\n if (url && !url.startsWith(\"http\"))\n url = \"http://\" + url;\n return url;\n };\n return _this;\n }\n CustomersController.prototype.client = function (api) {\n return api.customers;\n };\n CustomersController.prototype.newSearch = function () {\n return {\n modelType: enums.meta.Customer.$name,\n sortField: \"name\",\n descending: false,\n filters: this.getFiltersFromMeta(enums.meta.Customer.$name, true),\n roles: []\n };\n };\n CustomersController = __decorate([\n NgView({\n token: Token.CustomersView,\n inherit: [Token.SearchView]\n })\n ], CustomersController);\n return CustomersController;\n }(SearchController));\n\n var DialogController = /** @class */ (function (_super) {\n __extends(DialogController, _super);\n function DialogController($scope, dialogService) {\n var _this = _super.call(this) || this;\n _this.$scope = $scope;\n _this.dialogService = dialogService;\n $scope.model = {\n alerts: dialogService.alerts,\n dialogs: dialogService.dialogs\n };\n $scope.closeAlert = function (index) {\n dialogService.closeAlert(index);\n };\n return _this;\n }\n DialogController = __decorate([\n NgView({\n token: Token.DialogView,\n dependencies: [\n Token.$Scope,\n Token.DialogService,\n ]\n })\n ], DialogController);\n return DialogController;\n }(BaseController));\n\n var NotificationsController = /** @class */ (function (_super) {\n __extends(NotificationsController, _super);\n function NotificationsController($scope, agg) {\n var _this = _super.call(this, $scope, agg) || this;\n $scope.allowSearch = false;\n agg.drawerService.pageTitle = loc.notifications;\n agg.drawerService.pageIcon = _tools.icons.email;\n agg.drawerService.setHelpUrl(\"Notifications\");\n return _this;\n }\n NotificationsController.prototype.client = function (api) {\n return api.notifications;\n };\n NotificationsController.prototype.newSearch = function () {\n return {\n modelType: enums.meta.Notification.$name,\n sortField: \"createdDate\",\n descending: true,\n filters: this.getFiltersFromMeta(enums.meta.Notification.$name, true),\n roles: []\n };\n };\n NotificationsController = __decorate([\n NgView({\n token: Token.NotificationsView,\n inherit: [Token.SearchView]\n })\n ], NotificationsController);\n return NotificationsController;\n }(SearchController));\n\n var DrawerController = /** @class */ (function (_super) {\n __extends(DrawerController, _super);\n function DrawerController($scope, drawerService, $timeout) {\n var _this = _super.call(this) || this;\n _this.$scope = $scope;\n _this.drawerService = drawerService;\n $scope.drawerService = drawerService;\n // routine for resizing drawer buttons if there are too many\n var resizeDrawer = _tools.Utils.throttle(function () {\n var $drawerButtons = jQuery(\".kb-drawer__buttons\");\n var totalWidth;\n $drawerButtons.find(\".kb-drawer__button\").each(function (i, e) {\n totalWidth += jQuery(e).outerWidth();\n });\n $drawerButtons.toggleClass(\"is-icons-only\", totalWidth > $drawerButtons.innerWidth());\n }, 100);\n $scope.$watchCollection(\"drawerService.drawers\", function () {\n resizeDrawer();\n });\n // track the window size\n jQuery(window).resize(function () {\n resizeDrawer();\n });\n return _this;\n }\n DrawerController = __decorate([\n NgView({\n token: Token.DrawerView,\n dependencies: [\n Token.$Scope,\n Token.DrawerService,\n Token.$Timeout,\n ]\n })\n ], DrawerController);\n return DrawerController;\n }(BaseController));\n\n (function (eLoginMode) {\n eLoginMode[eLoginMode[\"login\"] = 0] = \"login\";\n eLoginMode[eLoginMode[\"register\"] = 1] = \"register\";\n eLoginMode[eLoginMode[\"thanks\"] = 2] = \"thanks\";\n eLoginMode[eLoginMode[\"forgotPassword\"] = 3] = \"forgotPassword\";\n eLoginMode[eLoginMode[\"forgotPasswordSubmitted\"] = 4] = \"forgotPasswordSubmitted\";\n })(exports.eLoginMode || (exports.eLoginMode = {}));\n var LoginController = /** @class */ (function (_super) {\n __extends(LoginController, _super);\n function LoginController($scope, $http, authService, $rootScope, $timeout, $window, $location) {\n var _this = _super.call(this) || this;\n _this.$scope = $scope;\n _this.$http = $http;\n _this.authService = authService;\n _this.$rootScope = $rootScope;\n _this.$timeout = $timeout;\n _this.$window = $window;\n _this.$location = $location;\n $scope.mode = exports.eLoginMode.login;\n $scope.loginModel = {};\n $scope.userModel = {};\n $scope.forgotPasswordModel = {};\n $scope.registrationModel = {};\n $scope.ssoEnabled = $rootScope.context.ssoEnabled;\n $scope.login = function () {\n authService.login($scope.loginModel.email, $scope.loginModel.password, $scope.loginModel.rememberMe).finally(function () {\n $scope.loginError = authService.loginError;\n });\n };\n $scope.loginVisible = false;\n $scope.setMode = function (mode) {\n $scope.mode = mode;\n };\n $scope.ssoSignIn = function () {\n if (_tools.Utils.isDefined($location.search().embedded)) {\n _tools.Utils.sendMessageToParent({\n name: \"loginsso\",\n data: {}\n });\n }\n else {\n $window.location.href = \"/ssosignin?RedirectUrl=\" + $window.location.href;\n }\n };\n $scope.showAltLogin = function () {\n $scope.altLogin = true;\n };\n var off1 = $rootScope.$on(_tools.events.loginRequested, function () {\n if ($scope.ssoEnabled && _tools.Utils.getParameterByName($window.location.href, \"autoSsoLogin\")) {\n $scope.ssoSignIn();\n }\n $scope.loginVisible = true;\n });\n var off2 = $rootScope.$on(_tools.events.loginSuccessful, function () {\n _this.$timeout(function () {\n // delay emptying while the fade out animation runs\n $scope.loginVisible = false;\n $scope.loginModel.email = \"\";\n $scope.loginModel.password = \"\";\n }, 500);\n });\n $scope.register = function () {\n if (!$scope.registrationModel.agreedToPrivacyPolicy) {\n $scope.validation = { agreedToPrivacyPolicy: \"You must agree to the privacy policy before continuing\" };\n return;\n }\n return $http.post(\"/api/auth/register\", $scope.userModel, { tracker: $rootScope.loginTracker }).then(function () {\n $scope.mode = exports.eLoginMode.thanks;\n }, function (r) {\n $scope.validation = CrudController.prototype.getValidationObject(r.data, r.status);\n });\n };\n $scope.submitForgotPassword = function () {\n return $http.post(\"/api/auth/forgotpassword\", $scope.forgotPasswordModel, { tracker: $rootScope.loginTracker }).then(function () {\n $scope.mode = exports.eLoginMode.forgotPasswordSubmitted;\n }, function (r) {\n $scope.validation = CrudController.prototype.getValidationObject(r.data, r.status);\n });\n };\n if (!$rootScope.context.user && (!$rootScope.context.allowAnonymousLogins || $rootScope.environment !== enums.eEnvironment.prod) && _tools.Utils.getParameterByName($window.location.href, \"autoSsoLogin\")) {\n $scope.ssoSignIn();\n }\n $scope.$on(\"$destroy\", function () {\n off1();\n off2();\n });\n return _this;\n }\n LoginController = __decorate([\n NgView({\n token: Token.LoginView,\n dependencies: [\n Token.$Scope,\n Token.$Http,\n Token.AuthService,\n Token.$RootScope,\n Token.$Timeout,\n Token.$Window,\n Token.$Location\n ]\n })\n ], LoginController);\n return LoginController;\n }(BaseController));\n\n var PortalController = /** @class */ (function () {\n function PortalController($scope, $http, authService, $rootScope, $window, quoteService, $location, signalrService, sfdcService, storageService, agg) {\n var _this = this;\n this.$scope = $scope;\n this.$http = $http;\n this.authService = authService;\n this.$rootScope = $rootScope;\n this.$window = $window;\n this.quoteService = quoteService;\n this.$location = $location;\n this.signalrService = signalrService;\n this.sfdcService = sfdcService;\n this.storageService = storageService;\n this.agg = agg;\n $scope.model = {};\n $scope.notifications = [];\n $scope.pendingApprovals = [];\n $scope.sfdcService = sfdcService;\n $scope.$watch(function () { return quoteService.quote; }, function (opp) {\n $scope.model.quote = opp;\n });\n $scope.goToQuote = function () {\n quoteService.goToQuote();\n };\n $scope.login = function () {\n $rootScope.user = null;\n $rootScope.$broadcast(_tools.events.loginRequested);\n };\n $scope.logout = function () {\n authService.logout();\n };\n $scope.showMobileMenu = function () {\n $scope.model.mobileMenuVisible = true;\n };\n $scope.hideMobileMenu = function () {\n $scope.model.mobileMenuVisible = false;\n };\n var refreshNotifications = function () {\n $http.get(\"/api/notifications\", {\n params: { pageSize: 10 },\n ignoreSecurity: true\n }).then(function (r) {\n $scope.notifications.clear();\n $scope.notifications.pushArray(r.data.items);\n });\n };\n var onNotificationSignal = function () {\n // fill in notifications\n refreshNotifications();\n };\n var offOnLogin = $rootScope.$on(_tools.events.loginSuccessful, function () {\n if ($rootScope.user.id != -1) {\n _this.signalrService.notificationInvoke(\"subscribe\", _this.$rootScope.company.uniqueName, _this.$rootScope.user.id);\n _this.signalrService.notificationOn(\"notification\", onNotificationSignal);\n }\n });\n $scope.$on(\"$destroy\", function () {\n offOnLogin();\n if ($rootScope.user.id != -1) {\n _this.signalrService.notificationInvoke(\"unsubscribe\", _this.$rootScope.company.uniqueName, _this.$rootScope.user.id);\n _this.signalrService.notificationOff(\"notification\", onNotificationSignal);\n }\n });\n authService.authPromise.then(function () {\n // fill in company subdomains to drive the company selection for admins\n if ($rootScope.user.isAdmin) {\n $http.get(\"/api/companies/subdomains\").then(function (r) {\n $scope.companySubdomains = r.data;\n });\n }\n $scope.browseToSubdomain = function (subdomain) {\n var segments = $window.location.host.split(\".\");\n $window.location.href = \"https://\" + subdomain + \".\" + segments[1] + \".\" + segments[2];\n };\n if ($rootScope.user.id != -1) {\n // fill in pending approvals\n $http.get(\"/api/pendingapprovals\", {\n params: { pageSize: 4 },\n ignoreSecurity: true\n }).then(function (r) {\n $scope.pendingApprovals.pushArray(r.data.items);\n });\n // fill in notifications\n refreshNotifications();\n }\n });\n // fill in environments for environment selector\n $scope.environments = [];\n $scope.environments.push(enums.eEnvironment.dev);\n $scope.environments.push(enums.eEnvironment.test);\n $scope.environments.push(enums.eEnvironment.prod);\n $scope.browseToEnvironment = function (env) {\n if (env == $rootScope.environment)\n return;\n var envSuffix = \"\";\n if (env != enums.eEnvironment.prod) {\n envSuffix = \"-\" + env;\n }\n var segments = $window.location.host.split(\".\");\n $window.location.href =\n \"https://\" + $rootScope.company.subdomain + envSuffix + \".\" + segments[1] + \".\" + segments[2];\n };\n var focusin = function (e) {\n var phase = $rootScope.$$phase;\n if (phase == \"$apply\" || phase == \"$digest\") {\n $scope.mobileKeyboard = true;\n }\n else {\n $scope.$apply(function () {\n $scope.mobileKeyboard = true;\n });\n }\n };\n var focusout = function (e) {\n var phase = $rootScope.$$phase;\n if (phase == \"$apply\" || phase == \"$digest\") {\n $scope.mobileKeyboard = false;\n }\n else {\n $scope.$apply(function () {\n $scope.mobileKeyboard = false;\n });\n }\n };\n $(document).on(\"focusin\", \"input[type='text']\", focusin);\n $(document).on(\"focusout\", \"input[type='text']\", focusout);\n $scope.readNotification = function (notification, navigate) {\n if (navigate === void 0) { navigate = true; }\n $http.post(\"/api/notifications/markasread\", [notification.id]);\n // mark as read locally too\n $scope.notifications.find(function (n) {\n return n.id == notification.id;\n }).read = true;\n if (navigate)\n $location.path(notification.urlPath);\n };\n $scope.markAllNotificationsAsRead = function () {\n $scope.notifications.forEach(function (n) {\n $scope.readNotification(n, false);\n });\n };\n $scope.newNotificationCount = function () {\n return $scope.pendingApprovals.length + $scope.notifications.filter(function (n) { return !n.read; }).length;\n };\n $scope.$on(\"$destroy\", function () {\n $(document).off(\"focusin\", \"input[type='text']\", focusin);\n $(document).off(\"focusout\", \"input[type='text']\", focusout);\n });\n if ($rootScope.context.company.snapStudioMode) {\n $rootScope.hideHeader = true;\n }\n }\n PortalController = __decorate([\n NgView({\n token: Token.PortalView,\n dependencies: [\n Token.$Scope,\n Token.$Http,\n Token.AuthService,\n Token.$RootScope,\n Token.$Window,\n Token.QuoteService,\n Token.$Location,\n Token.SignalRService,\n Token.SfdcService,\n Token.StorageService,\n Token.CrudService\n ]\n })\n ], PortalController);\n return PortalController;\n }());\n\n var PrivacyPolicyController = /** @class */ (function (_super) {\n __extends(PrivacyPolicyController, _super);\n function PrivacyPolicyController($scope, api, $rootScope, dialogService, authService) {\n var _this = _super.call(this) || this;\n _this.$scope = $scope;\n _this.api = api;\n _this.$rootScope = $rootScope;\n _this.dialogService = dialogService;\n _this.authService = authService;\n $scope.privacyPolicyModel = {};\n $scope.logout = function () {\n authService.logout();\n };\n $scope.agree = function () {\n if (!$scope.privacyPolicyModel.agreed) {\n dialogService.alert({\n msg: \"Before you can continue you must agree to the privacy policy.\",\n type: enums.eAlertType.error,\n persist: true\n });\n return;\n }\n _this.api.users.acceptPrivacyPolicy().then(function (u) {\n $rootScope.user.hasLatestPrivacyPolicy = true;\n });\n };\n return _this;\n }\n PrivacyPolicyController = __decorate([\n NgView({\n token: Token.PrivacyPolicyView,\n dependencies: [\n Token.$Scope,\n Token.ApiService,\n Token.$RootScope,\n Token.DialogService,\n Token.AuthService\n ]\n })\n ], PrivacyPolicyController);\n return PrivacyPolicyController;\n }(BaseController));\n\n // can-promise has a crash in some versions of react native that dont have\n // standard global objects\n // https://github.com/soldair/node-qrcode/issues/157\n\n var canPromise = function () {\n return typeof Promise === 'function' && Promise.prototype && Promise.prototype.then\n };\n\n let toSJISFunction;\n const CODEWORDS_COUNT = [\n 0, // Not used\n 26, 44, 70, 100, 134, 172, 196, 242, 292, 346,\n 404, 466, 532, 581, 655, 733, 815, 901, 991, 1085,\n 1156, 1258, 1364, 1474, 1588, 1706, 1828, 1921, 2051, 2185,\n 2323, 2465, 2611, 2761, 2876, 3034, 3196, 3362, 3532, 3706\n ];\n\n /**\n * Returns the QR Code size for the specified version\n *\n * @param {Number} version QR Code version\n * @return {Number} size of QR code\n */\n var getSymbolSize = function getSymbolSize (version) {\n if (!version) throw new Error('\"version\" cannot be null or undefined')\n if (version < 1 || version > 40) throw new Error('\"version\" should be in range from 1 to 40')\n return version * 4 + 17\n };\n\n /**\n * Returns the total number of codewords used to store data and EC information.\n *\n * @param {Number} version QR Code version\n * @return {Number} Data length in bits\n */\n var getSymbolTotalCodewords = function getSymbolTotalCodewords (version) {\n return CODEWORDS_COUNT[version]\n };\n\n /**\n * Encode data with Bose-Chaudhuri-Hocquenghem\n *\n * @param {Number} data Value to encode\n * @return {Number} Encoded value\n */\n var getBCHDigit = function (data) {\n let digit = 0;\n\n while (data !== 0) {\n digit++;\n data >>>= 1;\n }\n\n return digit\n };\n\n var setToSJISFunction = function setToSJISFunction (f) {\n if (typeof f !== 'function') {\n throw new Error('\"toSJISFunc\" is not a valid function.')\n }\n\n toSJISFunction = f;\n };\n\n var isKanjiModeEnabled = function () {\n return typeof toSJISFunction !== 'undefined'\n };\n\n var toSJIS = function toSJIS (kanji) {\n return toSJISFunction(kanji)\n };\n\n var utils = {\n \tgetSymbolSize: getSymbolSize,\n \tgetSymbolTotalCodewords: getSymbolTotalCodewords,\n \tgetBCHDigit: getBCHDigit,\n \tsetToSJISFunction: setToSJISFunction,\n \tisKanjiModeEnabled: isKanjiModeEnabled,\n \ttoSJIS: toSJIS\n };\n\n function createCommonjsModule(fn, basedir, module) {\n \treturn module = {\n \t\tpath: basedir,\n \t\texports: {},\n \t\trequire: function (path, base) {\n \t\t\treturn commonjsRequire(path, (base === undefined || base === null) ? module.path : base);\n \t\t}\n \t}, fn(module, module.exports), module.exports;\n }\n\n function commonjsRequire () {\n \tthrow new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs');\n }\n\n var errorCorrectionLevel = createCommonjsModule(function (module, exports) {\n exports.L = { bit: 1 };\n exports.M = { bit: 0 };\n exports.Q = { bit: 3 };\n exports.H = { bit: 2 };\n\n function fromString (string) {\n if (typeof string !== 'string') {\n throw new Error('Param is not a string')\n }\n\n const lcStr = string.toLowerCase();\n\n switch (lcStr) {\n case 'l':\n case 'low':\n return exports.L\n\n case 'm':\n case 'medium':\n return exports.M\n\n case 'q':\n case 'quartile':\n return exports.Q\n\n case 'h':\n case 'high':\n return exports.H\n\n default:\n throw new Error('Unknown EC Level: ' + string)\n }\n }\n\n exports.isValid = function isValid (level) {\n return level && typeof level.bit !== 'undefined' &&\n level.bit >= 0 && level.bit < 4\n };\n\n exports.from = function from (value, defaultValue) {\n if (exports.isValid(value)) {\n return value\n }\n\n try {\n return fromString(value)\n } catch (e) {\n return defaultValue\n }\n };\n });\n\n function BitBuffer () {\n this.buffer = [];\n this.length = 0;\n }\n\n BitBuffer.prototype = {\n\n get: function (index) {\n const bufIndex = Math.floor(index / 8);\n return ((this.buffer[bufIndex] >>> (7 - index % 8)) & 1) === 1\n },\n\n put: function (num, length) {\n for (let i = 0; i < length; i++) {\n this.putBit(((num >>> (length - i - 1)) & 1) === 1);\n }\n },\n\n getLengthInBits: function () {\n return this.length\n },\n\n putBit: function (bit) {\n const bufIndex = Math.floor(this.length / 8);\n if (this.buffer.length <= bufIndex) {\n this.buffer.push(0);\n }\n\n if (bit) {\n this.buffer[bufIndex] |= (0x80 >>> (this.length % 8));\n }\n\n this.length++;\n }\n };\n\n var bitBuffer = BitBuffer;\n\n /**\n * Helper class to handle QR Code symbol modules\n *\n * @param {Number} size Symbol size\n */\n function BitMatrix (size) {\n if (!size || size < 1) {\n throw new Error('BitMatrix size must be defined and greater than 0')\n }\n\n this.size = size;\n this.data = new Uint8Array(size * size);\n this.reservedBit = new Uint8Array(size * size);\n }\n\n /**\n * Set bit value at specified location\n * If reserved flag is set, this bit will be ignored during masking process\n *\n * @param {Number} row\n * @param {Number} col\n * @param {Boolean} value\n * @param {Boolean} reserved\n */\n BitMatrix.prototype.set = function (row, col, value, reserved) {\n const index = row * this.size + col;\n this.data[index] = value;\n if (reserved) this.reservedBit[index] = true;\n };\n\n /**\n * Returns bit value at specified location\n *\n * @param {Number} row\n * @param {Number} col\n * @return {Boolean}\n */\n BitMatrix.prototype.get = function (row, col) {\n return this.data[row * this.size + col]\n };\n\n /**\n * Applies xor operator at specified location\n * (used during masking process)\n *\n * @param {Number} row\n * @param {Number} col\n * @param {Boolean} value\n */\n BitMatrix.prototype.xor = function (row, col, value) {\n this.data[row * this.size + col] ^= value;\n };\n\n /**\n * Check if bit at specified location is reserved\n *\n * @param {Number} row\n * @param {Number} col\n * @return {Boolean}\n */\n BitMatrix.prototype.isReserved = function (row, col) {\n return this.reservedBit[row * this.size + col]\n };\n\n var bitMatrix = BitMatrix;\n\n var alignmentPattern = createCommonjsModule(function (module, exports) {\n /**\n * Alignment pattern are fixed reference pattern in defined positions\n * in a matrix symbology, which enables the decode software to re-synchronise\n * the coordinate mapping of the image modules in the event of moderate amounts\n * of distortion of the image.\n *\n * Alignment patterns are present only in QR Code symbols of version 2 or larger\n * and their number depends on the symbol version.\n */\n\n const getSymbolSize = utils.getSymbolSize;\n\n /**\n * Calculate the row/column coordinates of the center module of each alignment pattern\n * for the specified QR Code version.\n *\n * The alignment patterns are positioned symmetrically on either side of the diagonal\n * running from the top left corner of the symbol to the bottom right corner.\n *\n * Since positions are simmetrical only half of the coordinates are returned.\n * Each item of the array will represent in turn the x and y coordinate.\n * @see {@link getPositions}\n *\n * @param {Number} version QR Code version\n * @return {Array} Array of coordinate\n */\n exports.getRowColCoords = function getRowColCoords (version) {\n if (version === 1) return []\n\n const posCount = Math.floor(version / 7) + 2;\n const size = getSymbolSize(version);\n const intervals = size === 145 ? 26 : Math.ceil((size - 13) / (2 * posCount - 2)) * 2;\n const positions = [size - 7]; // Last coord is always (size - 7)\n\n for (let i = 1; i < posCount - 1; i++) {\n positions[i] = positions[i - 1] - intervals;\n }\n\n positions.push(6); // First coord is always 6\n\n return positions.reverse()\n };\n\n /**\n * Returns an array containing the positions of each alignment pattern.\n * Each array's element represent the center point of the pattern as (x, y) coordinates\n *\n * Coordinates are calculated expanding the row/column coordinates returned by {@link getRowColCoords}\n * and filtering out the items that overlaps with finder pattern\n *\n * @example\n * For a Version 7 symbol {@link getRowColCoords} returns values 6, 22 and 38.\n * The alignment patterns, therefore, are to be centered on (row, column)\n * positions (6,22), (22,6), (22,22), (22,38), (38,22), (38,38).\n * Note that the coordinates (6,6), (6,38), (38,6) are occupied by finder patterns\n * and are not therefore used for alignment patterns.\n *\n * let pos = getPositions(7)\n * // [[6,22], [22,6], [22,22], [22,38], [38,22], [38,38]]\n *\n * @param {Number} version QR Code version\n * @return {Array} Array of coordinates\n */\n exports.getPositions = function getPositions (version) {\n const coords = [];\n const pos = exports.getRowColCoords(version);\n const posLength = pos.length;\n\n for (let i = 0; i < posLength; i++) {\n for (let j = 0; j < posLength; j++) {\n // Skip if position is occupied by finder patterns\n if ((i === 0 && j === 0) || // top-left\n (i === 0 && j === posLength - 1) || // bottom-left\n (i === posLength - 1 && j === 0)) { // top-right\n continue\n }\n\n coords.push([pos[i], pos[j]]);\n }\n }\n\n return coords\n };\n });\n\n const getSymbolSize$1 = utils.getSymbolSize;\n const FINDER_PATTERN_SIZE = 7;\n\n /**\n * Returns an array containing the positions of each finder pattern.\n * Each array's element represent the top-left point of the pattern as (x, y) coordinates\n *\n * @param {Number} version QR Code version\n * @return {Array} Array of coordinates\n */\n var getPositions = function getPositions (version) {\n const size = getSymbolSize$1(version);\n\n return [\n // top-left\n [0, 0],\n // top-right\n [size - FINDER_PATTERN_SIZE, 0],\n // bottom-left\n [0, size - FINDER_PATTERN_SIZE]\n ]\n };\n\n var finderPattern = {\n \tgetPositions: getPositions\n };\n\n var maskPattern = createCommonjsModule(function (module, exports) {\n /**\n * Data mask pattern reference\n * @type {Object}\n */\n exports.Patterns = {\n PATTERN000: 0,\n PATTERN001: 1,\n PATTERN010: 2,\n PATTERN011: 3,\n PATTERN100: 4,\n PATTERN101: 5,\n PATTERN110: 6,\n PATTERN111: 7\n };\n\n /**\n * Weighted penalty scores for the undesirable features\n * @type {Object}\n */\n const PenaltyScores = {\n N1: 3,\n N2: 3,\n N3: 40,\n N4: 10\n };\n\n /**\n * Check if mask pattern value is valid\n *\n * @param {Number} mask Mask pattern\n * @return {Boolean} true if valid, false otherwise\n */\n exports.isValid = function isValid (mask) {\n return mask != null && mask !== '' && !isNaN(mask) && mask >= 0 && mask <= 7\n };\n\n /**\n * Returns mask pattern from a value.\n * If value is not valid, returns undefined\n *\n * @param {Number|String} value Mask pattern value\n * @return {Number} Valid mask pattern or undefined\n */\n exports.from = function from (value) {\n return exports.isValid(value) ? parseInt(value, 10) : undefined\n };\n\n /**\n * Find adjacent modules in row/column with the same color\n * and assign a penalty value.\n *\n * Points: N1 + i\n * i is the amount by which the number of adjacent modules of the same color exceeds 5\n */\n exports.getPenaltyN1 = function getPenaltyN1 (data) {\n const size = data.size;\n let points = 0;\n let sameCountCol = 0;\n let sameCountRow = 0;\n let lastCol = null;\n let lastRow = null;\n\n for (let row = 0; row < size; row++) {\n sameCountCol = sameCountRow = 0;\n lastCol = lastRow = null;\n\n for (let col = 0; col < size; col++) {\n let module = data.get(row, col);\n if (module === lastCol) {\n sameCountCol++;\n } else {\n if (sameCountCol >= 5) points += PenaltyScores.N1 + (sameCountCol - 5);\n lastCol = module;\n sameCountCol = 1;\n }\n\n module = data.get(col, row);\n if (module === lastRow) {\n sameCountRow++;\n } else {\n if (sameCountRow >= 5) points += PenaltyScores.N1 + (sameCountRow - 5);\n lastRow = module;\n sameCountRow = 1;\n }\n }\n\n if (sameCountCol >= 5) points += PenaltyScores.N1 + (sameCountCol - 5);\n if (sameCountRow >= 5) points += PenaltyScores.N1 + (sameCountRow - 5);\n }\n\n return points\n };\n\n /**\n * Find 2x2 blocks with the same color and assign a penalty value\n *\n * Points: N2 * (m - 1) * (n - 1)\n */\n exports.getPenaltyN2 = function getPenaltyN2 (data) {\n const size = data.size;\n let points = 0;\n\n for (let row = 0; row < size - 1; row++) {\n for (let col = 0; col < size - 1; col++) {\n const last = data.get(row, col) +\n data.get(row, col + 1) +\n data.get(row + 1, col) +\n data.get(row + 1, col + 1);\n\n if (last === 4 || last === 0) points++;\n }\n }\n\n return points * PenaltyScores.N2\n };\n\n /**\n * Find 1:1:3:1:1 ratio (dark:light:dark:light:dark) pattern in row/column,\n * preceded or followed by light area 4 modules wide\n *\n * Points: N3 * number of pattern found\n */\n exports.getPenaltyN3 = function getPenaltyN3 (data) {\n const size = data.size;\n let points = 0;\n let bitsCol = 0;\n let bitsRow = 0;\n\n for (let row = 0; row < size; row++) {\n bitsCol = bitsRow = 0;\n for (let col = 0; col < size; col++) {\n bitsCol = ((bitsCol << 1) & 0x7FF) | data.get(row, col);\n if (col >= 10 && (bitsCol === 0x5D0 || bitsCol === 0x05D)) points++;\n\n bitsRow = ((bitsRow << 1) & 0x7FF) | data.get(col, row);\n if (col >= 10 && (bitsRow === 0x5D0 || bitsRow === 0x05D)) points++;\n }\n }\n\n return points * PenaltyScores.N3\n };\n\n /**\n * Calculate proportion of dark modules in entire symbol\n *\n * Points: N4 * k\n *\n * k is the rating of the deviation of the proportion of dark modules\n * in the symbol from 50% in steps of 5%\n */\n exports.getPenaltyN4 = function getPenaltyN4 (data) {\n let darkCount = 0;\n const modulesCount = data.data.length;\n\n for (let i = 0; i < modulesCount; i++) darkCount += data.data[i];\n\n const k = Math.abs(Math.ceil((darkCount * 100 / modulesCount) / 5) - 10);\n\n return k * PenaltyScores.N4\n };\n\n /**\n * Return mask value at given position\n *\n * @param {Number} maskPattern Pattern reference value\n * @param {Number} i Row\n * @param {Number} j Column\n * @return {Boolean} Mask value\n */\n function getMaskAt (maskPattern, i, j) {\n switch (maskPattern) {\n case exports.Patterns.PATTERN000: return (i + j) % 2 === 0\n case exports.Patterns.PATTERN001: return i % 2 === 0\n case exports.Patterns.PATTERN010: return j % 3 === 0\n case exports.Patterns.PATTERN011: return (i + j) % 3 === 0\n case exports.Patterns.PATTERN100: return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 === 0\n case exports.Patterns.PATTERN101: return (i * j) % 2 + (i * j) % 3 === 0\n case exports.Patterns.PATTERN110: return ((i * j) % 2 + (i * j) % 3) % 2 === 0\n case exports.Patterns.PATTERN111: return ((i * j) % 3 + (i + j) % 2) % 2 === 0\n\n default: throw new Error('bad maskPattern:' + maskPattern)\n }\n }\n\n /**\n * Apply a mask pattern to a BitMatrix\n *\n * @param {Number} pattern Pattern reference number\n * @param {BitMatrix} data BitMatrix data\n */\n exports.applyMask = function applyMask (pattern, data) {\n const size = data.size;\n\n for (let col = 0; col < size; col++) {\n for (let row = 0; row < size; row++) {\n if (data.isReserved(row, col)) continue\n data.xor(row, col, getMaskAt(pattern, row, col));\n }\n }\n };\n\n /**\n * Returns the best mask pattern for data\n *\n * @param {BitMatrix} data\n * @return {Number} Mask pattern reference number\n */\n exports.getBestMask = function getBestMask (data, setupFormatFunc) {\n const numPatterns = Object.keys(exports.Patterns).length;\n let bestPattern = 0;\n let lowerPenalty = Infinity;\n\n for (let p = 0; p < numPatterns; p++) {\n setupFormatFunc(p);\n exports.applyMask(p, data);\n\n // Calculate penalty\n const penalty =\n exports.getPenaltyN1(data) +\n exports.getPenaltyN2(data) +\n exports.getPenaltyN3(data) +\n exports.getPenaltyN4(data);\n\n // Undo previously applied mask\n exports.applyMask(p, data);\n\n if (penalty < lowerPenalty) {\n lowerPenalty = penalty;\n bestPattern = p;\n }\n }\n\n return bestPattern\n };\n });\n\n const EC_BLOCKS_TABLE = [\r\n // L M Q H\r\n 1, 1, 1, 1,\r\n 1, 1, 1, 1,\r\n 1, 1, 2, 2,\r\n 1, 2, 2, 4,\r\n 1, 2, 4, 4,\r\n 2, 4, 4, 4,\r\n 2, 4, 6, 5,\r\n 2, 4, 6, 6,\r\n 2, 5, 8, 8,\r\n 4, 5, 8, 8,\r\n 4, 5, 8, 11,\r\n 4, 8, 10, 11,\r\n 4, 9, 12, 16,\r\n 4, 9, 16, 16,\r\n 6, 10, 12, 18,\r\n 6, 10, 17, 16,\r\n 6, 11, 16, 19,\r\n 6, 13, 18, 21,\r\n 7, 14, 21, 25,\r\n 8, 16, 20, 25,\r\n 8, 17, 23, 25,\r\n 9, 17, 23, 34,\r\n 9, 18, 25, 30,\r\n 10, 20, 27, 32,\r\n 12, 21, 29, 35,\r\n 12, 23, 34, 37,\r\n 12, 25, 34, 40,\r\n 13, 26, 35, 42,\r\n 14, 28, 38, 45,\r\n 15, 29, 40, 48,\r\n 16, 31, 43, 51,\r\n 17, 33, 45, 54,\r\n 18, 35, 48, 57,\r\n 19, 37, 51, 60,\r\n 19, 38, 53, 63,\r\n 20, 40, 56, 66,\r\n 21, 43, 59, 70,\r\n 22, 45, 62, 74,\r\n 24, 47, 65, 77,\r\n 25, 49, 68, 81\r\n ];\r\n\r\n const EC_CODEWORDS_TABLE = [\r\n // L M Q H\r\n 7, 10, 13, 17,\r\n 10, 16, 22, 28,\r\n 15, 26, 36, 44,\r\n 20, 36, 52, 64,\r\n 26, 48, 72, 88,\r\n 36, 64, 96, 112,\r\n 40, 72, 108, 130,\r\n 48, 88, 132, 156,\r\n 60, 110, 160, 192,\r\n 72, 130, 192, 224,\r\n 80, 150, 224, 264,\r\n 96, 176, 260, 308,\r\n 104, 198, 288, 352,\r\n 120, 216, 320, 384,\r\n 132, 240, 360, 432,\r\n 144, 280, 408, 480,\r\n 168, 308, 448, 532,\r\n 180, 338, 504, 588,\r\n 196, 364, 546, 650,\r\n 224, 416, 600, 700,\r\n 224, 442, 644, 750,\r\n 252, 476, 690, 816,\r\n 270, 504, 750, 900,\r\n 300, 560, 810, 960,\r\n 312, 588, 870, 1050,\r\n 336, 644, 952, 1110,\r\n 360, 700, 1020, 1200,\r\n 390, 728, 1050, 1260,\r\n 420, 784, 1140, 1350,\r\n 450, 812, 1200, 1440,\r\n 480, 868, 1290, 1530,\r\n 510, 924, 1350, 1620,\r\n 540, 980, 1440, 1710,\r\n 570, 1036, 1530, 1800,\r\n 570, 1064, 1590, 1890,\r\n 600, 1120, 1680, 1980,\r\n 630, 1204, 1770, 2100,\r\n 660, 1260, 1860, 2220,\r\n 720, 1316, 1950, 2310,\r\n 750, 1372, 2040, 2430\r\n ];\r\n\r\n /**\r\n * Returns the number of error correction block that the QR Code should contain\r\n * for the specified version and error correction level.\r\n *\r\n * @param {Number} version QR Code version\r\n * @param {Number} errorCorrectionLevel Error correction level\r\n * @return {Number} Number of error correction blocks\r\n */\r\n var getBlocksCount = function getBlocksCount (version, errorCorrectionLevel$1) {\r\n switch (errorCorrectionLevel$1) {\r\n case errorCorrectionLevel.L:\r\n return EC_BLOCKS_TABLE[(version - 1) * 4 + 0]\r\n case errorCorrectionLevel.M:\r\n return EC_BLOCKS_TABLE[(version - 1) * 4 + 1]\r\n case errorCorrectionLevel.Q:\r\n return EC_BLOCKS_TABLE[(version - 1) * 4 + 2]\r\n case errorCorrectionLevel.H:\r\n return EC_BLOCKS_TABLE[(version - 1) * 4 + 3]\r\n default:\r\n return undefined\r\n }\r\n };\r\n\r\n /**\r\n * Returns the number of error correction codewords to use for the specified\r\n * version and error correction level.\r\n *\r\n * @param {Number} version QR Code version\r\n * @param {Number} errorCorrectionLevel Error correction level\r\n * @return {Number} Number of error correction codewords\r\n */\r\n var getTotalCodewordsCount = function getTotalCodewordsCount (version, errorCorrectionLevel$1) {\r\n switch (errorCorrectionLevel$1) {\r\n case errorCorrectionLevel.L:\r\n return EC_CODEWORDS_TABLE[(version - 1) * 4 + 0]\r\n case errorCorrectionLevel.M:\r\n return EC_CODEWORDS_TABLE[(version - 1) * 4 + 1]\r\n case errorCorrectionLevel.Q:\r\n return EC_CODEWORDS_TABLE[(version - 1) * 4 + 2]\r\n case errorCorrectionLevel.H:\r\n return EC_CODEWORDS_TABLE[(version - 1) * 4 + 3]\r\n default:\r\n return undefined\r\n }\r\n };\n\n var errorCorrectionCode = {\n \tgetBlocksCount: getBlocksCount,\n \tgetTotalCodewordsCount: getTotalCodewordsCount\n };\n\n const EXP_TABLE = new Uint8Array(512);\n const LOG_TABLE = new Uint8Array(256)\n /**\n * Precompute the log and anti-log tables for faster computation later\n *\n * For each possible value in the galois field 2^8, we will pre-compute\n * the logarithm and anti-logarithm (exponential) of this value\n *\n * ref {@link https://en.wikiversity.org/wiki/Reed%E2%80%93Solomon_codes_for_coders#Introduction_to_mathematical_fields}\n */\n ;(function initTables () {\n let x = 1;\n for (let i = 0; i < 255; i++) {\n EXP_TABLE[i] = x;\n LOG_TABLE[x] = i;\n\n x <<= 1; // multiply by 2\n\n // The QR code specification says to use byte-wise modulo 100011101 arithmetic.\n // This means that when a number is 256 or larger, it should be XORed with 0x11D.\n if (x & 0x100) { // similar to x >= 256, but a lot faster (because 0x100 == 256)\n x ^= 0x11D;\n }\n }\n\n // Optimization: double the size of the anti-log table so that we don't need to mod 255 to\n // stay inside the bounds (because we will mainly use this table for the multiplication of\n // two GF numbers, no more).\n // @see {@link mul}\n for (let i = 255; i < 512; i++) {\n EXP_TABLE[i] = EXP_TABLE[i - 255];\n }\n }());\n\n /**\n * Returns log value of n inside Galois Field\n *\n * @param {Number} n\n * @return {Number}\n */\n var log = function log (n) {\n if (n < 1) throw new Error('log(' + n + ')')\n return LOG_TABLE[n]\n };\n\n /**\n * Returns anti-log value of n inside Galois Field\n *\n * @param {Number} n\n * @return {Number}\n */\n var exp = function exp (n) {\n return EXP_TABLE[n]\n };\n\n /**\n * Multiplies two number inside Galois Field\n *\n * @param {Number} x\n * @param {Number} y\n * @return {Number}\n */\n var mul = function mul (x, y) {\n if (x === 0 || y === 0) return 0\n\n // should be EXP_TABLE[(LOG_TABLE[x] + LOG_TABLE[y]) % 255] if EXP_TABLE wasn't oversized\n // @see {@link initTables}\n return EXP_TABLE[LOG_TABLE[x] + LOG_TABLE[y]]\n };\n\n var galoisField = {\n \tlog: log,\n \texp: exp,\n \tmul: mul\n };\n\n var polynomial = createCommonjsModule(function (module, exports) {\n /**\n * Multiplies two polynomials inside Galois Field\n *\n * @param {Uint8Array} p1 Polynomial\n * @param {Uint8Array} p2 Polynomial\n * @return {Uint8Array} Product of p1 and p2\n */\n exports.mul = function mul (p1, p2) {\n const coeff = new Uint8Array(p1.length + p2.length - 1);\n\n for (let i = 0; i < p1.length; i++) {\n for (let j = 0; j < p2.length; j++) {\n coeff[i + j] ^= galoisField.mul(p1[i], p2[j]);\n }\n }\n\n return coeff\n };\n\n /**\n * Calculate the remainder of polynomials division\n *\n * @param {Uint8Array} divident Polynomial\n * @param {Uint8Array} divisor Polynomial\n * @return {Uint8Array} Remainder\n */\n exports.mod = function mod (divident, divisor) {\n let result = new Uint8Array(divident);\n\n while ((result.length - divisor.length) >= 0) {\n const coeff = result[0];\n\n for (let i = 0; i < divisor.length; i++) {\n result[i] ^= galoisField.mul(divisor[i], coeff);\n }\n\n // remove all zeros from buffer head\n let offset = 0;\n while (offset < result.length && result[offset] === 0) offset++;\n result = result.slice(offset);\n }\n\n return result\n };\n\n /**\n * Generate an irreducible generator polynomial of specified degree\n * (used by Reed-Solomon encoder)\n *\n * @param {Number} degree Degree of the generator polynomial\n * @return {Uint8Array} Buffer containing polynomial coefficients\n */\n exports.generateECPolynomial = function generateECPolynomial (degree) {\n let poly = new Uint8Array([1]);\n for (let i = 0; i < degree; i++) {\n poly = exports.mul(poly, new Uint8Array([1, galoisField.exp(i)]));\n }\n\n return poly\n };\n });\n\n function ReedSolomonEncoder (degree) {\n this.genPoly = undefined;\n this.degree = degree;\n\n if (this.degree) this.initialize(this.degree);\n }\n\n /**\n * Initialize the encoder.\n * The input param should correspond to the number of error correction codewords.\n *\n * @param {Number} degree\n */\n ReedSolomonEncoder.prototype.initialize = function initialize (degree) {\n // create an irreducible generator polynomial\n this.degree = degree;\n this.genPoly = polynomial.generateECPolynomial(this.degree);\n };\n\n /**\n * Encodes a chunk of data\n *\n * @param {Uint8Array} data Buffer containing input data\n * @return {Uint8Array} Buffer containing encoded data\n */\n ReedSolomonEncoder.prototype.encode = function encode (data) {\n if (!this.genPoly) {\n throw new Error('Encoder not initialized')\n }\n\n // Calculate EC for this data block\n // extends data size to data+genPoly size\n const paddedData = new Uint8Array(data.length + this.degree);\n paddedData.set(data);\n\n // The error correction codewords are the remainder after dividing the data codewords\n // by a generator polynomial\n const remainder = polynomial.mod(paddedData, this.genPoly);\n\n // return EC data blocks (last n byte, where n is the degree of genPoly)\n // If coefficients number in remainder are less than genPoly degree,\n // pad with 0s to the left to reach the needed number of coefficients\n const start = this.degree - remainder.length;\n if (start > 0) {\n const buff = new Uint8Array(this.degree);\n buff.set(remainder, start);\n\n return buff\n }\n\n return remainder\n };\n\n var reedSolomonEncoder = ReedSolomonEncoder;\n\n /**\n * Check if QR Code version is valid\n *\n * @param {Number} version QR Code version\n * @return {Boolean} true if valid version, false otherwise\n */\n var isValid = function isValid (version) {\n return !isNaN(version) && version >= 1 && version <= 40\n };\n\n var versionCheck = {\n \tisValid: isValid\n };\n\n const numeric = '[0-9]+';\n const alphanumeric = '[A-Z $%*+\\\\-./:]+';\n let kanji = '(?:[u3000-u303F]|[u3040-u309F]|[u30A0-u30FF]|' +\n '[uFF00-uFFEF]|[u4E00-u9FAF]|[u2605-u2606]|[u2190-u2195]|u203B|' +\n '[u2010u2015u2018u2019u2025u2026u201Cu201Du2225u2260]|' +\n '[u0391-u0451]|[u00A7u00A8u00B1u00B4u00D7u00F7])+';\n kanji = kanji.replace(/u/g, '\\\\u');\n\n const byte = '(?:(?![A-Z0-9 $%*+\\\\-./:]|' + kanji + ')(?:.|[\\r\\n]))+';\n\n var KANJI = new RegExp(kanji, 'g');\n var BYTE_KANJI = new RegExp('[^A-Z0-9 $%*+\\\\-./:]+', 'g');\n var BYTE = new RegExp(byte, 'g');\n var NUMERIC = new RegExp(numeric, 'g');\n var ALPHANUMERIC = new RegExp(alphanumeric, 'g');\n\n const TEST_KANJI = new RegExp('^' + kanji + '$');\n const TEST_NUMERIC = new RegExp('^' + numeric + '$');\n const TEST_ALPHANUMERIC = new RegExp('^[A-Z0-9 $%*+\\\\-./:]+$');\n\n var testKanji = function testKanji (str) {\n return TEST_KANJI.test(str)\n };\n\n var testNumeric = function testNumeric (str) {\n return TEST_NUMERIC.test(str)\n };\n\n var testAlphanumeric = function testAlphanumeric (str) {\n return TEST_ALPHANUMERIC.test(str)\n };\n\n var regex = {\n \tKANJI: KANJI,\n \tBYTE_KANJI: BYTE_KANJI,\n \tBYTE: BYTE,\n \tNUMERIC: NUMERIC,\n \tALPHANUMERIC: ALPHANUMERIC,\n \ttestKanji: testKanji,\n \ttestNumeric: testNumeric,\n \ttestAlphanumeric: testAlphanumeric\n };\n\n var mode = createCommonjsModule(function (module, exports) {\n /**\n * Numeric mode encodes data from the decimal digit set (0 - 9)\n * (byte values 30HEX to 39HEX).\n * Normally, 3 data characters are represented by 10 bits.\n *\n * @type {Object}\n */\n exports.NUMERIC = {\n id: 'Numeric',\n bit: 1 << 0,\n ccBits: [10, 12, 14]\n };\n\n /**\n * Alphanumeric mode encodes data from a set of 45 characters,\n * i.e. 10 numeric digits (0 - 9),\n * 26 alphabetic characters (A - Z),\n * and 9 symbols (SP, $, %, *, +, -, ., /, :).\n * Normally, two input characters are represented by 11 bits.\n *\n * @type {Object}\n */\n exports.ALPHANUMERIC = {\n id: 'Alphanumeric',\n bit: 1 << 1,\n ccBits: [9, 11, 13]\n };\n\n /**\n * In byte mode, data is encoded at 8 bits per character.\n *\n * @type {Object}\n */\n exports.BYTE = {\n id: 'Byte',\n bit: 1 << 2,\n ccBits: [8, 16, 16]\n };\n\n /**\n * The Kanji mode efficiently encodes Kanji characters in accordance with\n * the Shift JIS system based on JIS X 0208.\n * The Shift JIS values are shifted from the JIS X 0208 values.\n * JIS X 0208 gives details of the shift coded representation.\n * Each two-byte character value is compacted to a 13-bit binary codeword.\n *\n * @type {Object}\n */\n exports.KANJI = {\n id: 'Kanji',\n bit: 1 << 3,\n ccBits: [8, 10, 12]\n };\n\n /**\n * Mixed mode will contain a sequences of data in a combination of any of\n * the modes described above\n *\n * @type {Object}\n */\n exports.MIXED = {\n bit: -1\n };\n\n /**\n * Returns the number of bits needed to store the data length\n * according to QR Code specifications.\n *\n * @param {Mode} mode Data mode\n * @param {Number} version QR Code version\n * @return {Number} Number of bits\n */\n exports.getCharCountIndicator = function getCharCountIndicator (mode, version) {\n if (!mode.ccBits) throw new Error('Invalid mode: ' + mode)\n\n if (!versionCheck.isValid(version)) {\n throw new Error('Invalid version: ' + version)\n }\n\n if (version >= 1 && version < 10) return mode.ccBits[0]\n else if (version < 27) return mode.ccBits[1]\n return mode.ccBits[2]\n };\n\n /**\n * Returns the most efficient mode to store the specified data\n *\n * @param {String} dataStr Input data string\n * @return {Mode} Best mode\n */\n exports.getBestModeForData = function getBestModeForData (dataStr) {\n if (regex.testNumeric(dataStr)) return exports.NUMERIC\n else if (regex.testAlphanumeric(dataStr)) return exports.ALPHANUMERIC\n else if (regex.testKanji(dataStr)) return exports.KANJI\n else return exports.BYTE\n };\n\n /**\n * Return mode name as string\n *\n * @param {Mode} mode Mode object\n * @returns {String} Mode name\n */\n exports.toString = function toString (mode) {\n if (mode && mode.id) return mode.id\n throw new Error('Invalid mode')\n };\n\n /**\n * Check if input param is a valid mode object\n *\n * @param {Mode} mode Mode object\n * @returns {Boolean} True if valid mode, false otherwise\n */\n exports.isValid = function isValid (mode) {\n return mode && mode.bit && mode.ccBits\n };\n\n /**\n * Get mode object from its name\n *\n * @param {String} string Mode name\n * @returns {Mode} Mode object\n */\n function fromString (string) {\n if (typeof string !== 'string') {\n throw new Error('Param is not a string')\n }\n\n const lcStr = string.toLowerCase();\n\n switch (lcStr) {\n case 'numeric':\n return exports.NUMERIC\n case 'alphanumeric':\n return exports.ALPHANUMERIC\n case 'kanji':\n return exports.KANJI\n case 'byte':\n return exports.BYTE\n default:\n throw new Error('Unknown mode: ' + string)\n }\n }\n\n /**\n * Returns mode from a value.\n * If value is not a valid mode, returns defaultValue\n *\n * @param {Mode|String} value Encoding mode\n * @param {Mode} defaultValue Fallback value\n * @return {Mode} Encoding mode\n */\n exports.from = function from (value, defaultValue) {\n if (exports.isValid(value)) {\n return value\n }\n\n try {\n return fromString(value)\n } catch (e) {\n return defaultValue\n }\n };\n });\n\n var version = createCommonjsModule(function (module, exports) {\n // Generator polynomial used to encode version information\n const G18 = (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0);\n const G18_BCH = utils.getBCHDigit(G18);\n\n function getBestVersionForDataLength (mode, length, errorCorrectionLevel) {\n for (let currentVersion = 1; currentVersion <= 40; currentVersion++) {\n if (length <= exports.getCapacity(currentVersion, errorCorrectionLevel, mode)) {\n return currentVersion\n }\n }\n\n return undefined\n }\n\n function getReservedBitsCount (mode$1, version) {\n // Character count indicator + mode indicator bits\n return mode.getCharCountIndicator(mode$1, version) + 4\n }\n\n function getTotalBitsFromDataArray (segments, version) {\n let totalBits = 0;\n\n segments.forEach(function (data) {\n const reservedBits = getReservedBitsCount(data.mode, version);\n totalBits += reservedBits + data.getBitsLength();\n });\n\n return totalBits\n }\n\n function getBestVersionForMixedData (segments, errorCorrectionLevel) {\n for (let currentVersion = 1; currentVersion <= 40; currentVersion++) {\n const length = getTotalBitsFromDataArray(segments, currentVersion);\n if (length <= exports.getCapacity(currentVersion, errorCorrectionLevel, mode.MIXED)) {\n return currentVersion\n }\n }\n\n return undefined\n }\n\n /**\n * Returns version number from a value.\n * If value is not a valid version, returns defaultValue\n *\n * @param {Number|String} value QR Code version\n * @param {Number} defaultValue Fallback value\n * @return {Number} QR Code version number\n */\n exports.from = function from (value, defaultValue) {\n if (versionCheck.isValid(value)) {\n return parseInt(value, 10)\n }\n\n return defaultValue\n };\n\n /**\n * Returns how much data can be stored with the specified QR code version\n * and error correction level\n *\n * @param {Number} version QR Code version (1-40)\n * @param {Number} errorCorrectionLevel Error correction level\n * @param {Mode} mode Data mode\n * @return {Number} Quantity of storable data\n */\n exports.getCapacity = function getCapacity (version, errorCorrectionLevel, mode$1) {\n if (!versionCheck.isValid(version)) {\n throw new Error('Invalid QR Code version')\n }\n\n // Use Byte mode as default\n if (typeof mode$1 === 'undefined') mode$1 = mode.BYTE;\n\n // Total codewords for this QR code version (Data + Error correction)\n const totalCodewords = utils.getSymbolTotalCodewords(version);\n\n // Total number of error correction codewords\n const ecTotalCodewords = errorCorrectionCode.getTotalCodewordsCount(version, errorCorrectionLevel);\n\n // Total number of data codewords\n const dataTotalCodewordsBits = (totalCodewords - ecTotalCodewords) * 8;\n\n if (mode$1 === mode.MIXED) return dataTotalCodewordsBits\n\n const usableBits = dataTotalCodewordsBits - getReservedBitsCount(mode$1, version);\n\n // Return max number of storable codewords\n switch (mode$1) {\n case mode.NUMERIC:\n return Math.floor((usableBits / 10) * 3)\n\n case mode.ALPHANUMERIC:\n return Math.floor((usableBits / 11) * 2)\n\n case mode.KANJI:\n return Math.floor(usableBits / 13)\n\n case mode.BYTE:\n default:\n return Math.floor(usableBits / 8)\n }\n };\n\n /**\n * Returns the minimum version needed to contain the amount of data\n *\n * @param {Segment} data Segment of data\n * @param {Number} [errorCorrectionLevel=H] Error correction level\n * @param {Mode} mode Data mode\n * @return {Number} QR Code version\n */\n exports.getBestVersionForData = function getBestVersionForData (data, errorCorrectionLevel$1) {\n let seg;\n\n const ecl = errorCorrectionLevel.from(errorCorrectionLevel$1, errorCorrectionLevel.M);\n\n if (Array.isArray(data)) {\n if (data.length > 1) {\n return getBestVersionForMixedData(data, ecl)\n }\n\n if (data.length === 0) {\n return 1\n }\n\n seg = data[0];\n } else {\n seg = data;\n }\n\n return getBestVersionForDataLength(seg.mode, seg.getLength(), ecl)\n };\n\n /**\n * Returns version information with relative error correction bits\n *\n * The version information is included in QR Code symbols of version 7 or larger.\n * It consists of an 18-bit sequence containing 6 data bits,\n * with 12 error correction bits calculated using the (18, 6) Golay code.\n *\n * @param {Number} version QR Code version\n * @return {Number} Encoded version info bits\n */\n exports.getEncodedBits = function getEncodedBits (version) {\n if (!versionCheck.isValid(version) || version < 7) {\n throw new Error('Invalid QR Code version')\n }\n\n let d = version << 12;\n\n while (utils.getBCHDigit(d) - G18_BCH >= 0) {\n d ^= (G18 << (utils.getBCHDigit(d) - G18_BCH));\n }\n\n return (version << 12) | d\n };\n });\n\n const G15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0);\n const G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1);\n const G15_BCH = utils.getBCHDigit(G15);\n\n /**\n * Returns format information with relative error correction bits\n *\n * The format information is a 15-bit sequence containing 5 data bits,\n * with 10 error correction bits calculated using the (15, 5) BCH code.\n *\n * @param {Number} errorCorrectionLevel Error correction level\n * @param {Number} mask Mask pattern\n * @return {Number} Encoded format information bits\n */\n var getEncodedBits = function getEncodedBits (errorCorrectionLevel, mask) {\n const data = ((errorCorrectionLevel.bit << 3) | mask);\n let d = data << 10;\n\n while (utils.getBCHDigit(d) - G15_BCH >= 0) {\n d ^= (G15 << (utils.getBCHDigit(d) - G15_BCH));\n }\n\n // xor final data with mask pattern in order to ensure that\n // no combination of Error Correction Level and data mask pattern\n // will result in an all-zero data string\n return ((data << 10) | d) ^ G15_MASK\n };\n\n var formatInfo = {\n \tgetEncodedBits: getEncodedBits\n };\n\n function NumericData (data) {\n this.mode = mode.NUMERIC;\n this.data = data.toString();\n }\n\n NumericData.getBitsLength = function getBitsLength (length) {\n return 10 * Math.floor(length / 3) + ((length % 3) ? ((length % 3) * 3 + 1) : 0)\n };\n\n NumericData.prototype.getLength = function getLength () {\n return this.data.length\n };\n\n NumericData.prototype.getBitsLength = function getBitsLength () {\n return NumericData.getBitsLength(this.data.length)\n };\n\n NumericData.prototype.write = function write (bitBuffer) {\n let i, group, value;\n\n // The input data string is divided into groups of three digits,\n // and each group is converted to its 10-bit binary equivalent.\n for (i = 0; i + 3 <= this.data.length; i += 3) {\n group = this.data.substr(i, 3);\n value = parseInt(group, 10);\n\n bitBuffer.put(value, 10);\n }\n\n // If the number of input digits is not an exact multiple of three,\n // the final one or two digits are converted to 4 or 7 bits respectively.\n const remainingNum = this.data.length - i;\n if (remainingNum > 0) {\n group = this.data.substr(i);\n value = parseInt(group, 10);\n\n bitBuffer.put(value, remainingNum * 3 + 1);\n }\n };\n\n var numericData = NumericData;\n\n /**\n * Array of characters available in alphanumeric mode\n *\n * As per QR Code specification, to each character\n * is assigned a value from 0 to 44 which in this case coincides\n * with the array index\n *\n * @type {Array}\n */\n const ALPHA_NUM_CHARS = [\n '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',\n 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',\n 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',\n ' ', '$', '%', '*', '+', '-', '.', '/', ':'\n ];\n\n function AlphanumericData (data) {\n this.mode = mode.ALPHANUMERIC;\n this.data = data;\n }\n\n AlphanumericData.getBitsLength = function getBitsLength (length) {\n return 11 * Math.floor(length / 2) + 6 * (length % 2)\n };\n\n AlphanumericData.prototype.getLength = function getLength () {\n return this.data.length\n };\n\n AlphanumericData.prototype.getBitsLength = function getBitsLength () {\n return AlphanumericData.getBitsLength(this.data.length)\n };\n\n AlphanumericData.prototype.write = function write (bitBuffer) {\n let i;\n\n // Input data characters are divided into groups of two characters\n // and encoded as 11-bit binary codes.\n for (i = 0; i + 2 <= this.data.length; i += 2) {\n // The character value of the first character is multiplied by 45\n let value = ALPHA_NUM_CHARS.indexOf(this.data[i]) * 45;\n\n // The character value of the second digit is added to the product\n value += ALPHA_NUM_CHARS.indexOf(this.data[i + 1]);\n\n // The sum is then stored as 11-bit binary number\n bitBuffer.put(value, 11);\n }\n\n // If the number of input data characters is not a multiple of two,\n // the character value of the final character is encoded as a 6-bit binary number.\n if (this.data.length % 2) {\n bitBuffer.put(ALPHA_NUM_CHARS.indexOf(this.data[i]), 6);\n }\n };\n\n var alphanumericData = AlphanumericData;\n\n var encodeUtf8 = function encodeUtf8 (input) {\n var result = [];\n var size = input.length;\n\n for (var index = 0; index < size; index++) {\n var point = input.charCodeAt(index);\n\n if (point >= 0xD800 && point <= 0xDBFF && size > index + 1) {\n var second = input.charCodeAt(index + 1);\n\n if (second >= 0xDC00 && second <= 0xDFFF) {\n // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae\n point = (point - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;\n index += 1;\n }\n }\n\n // US-ASCII\n if (point < 0x80) {\n result.push(point);\n continue\n }\n\n // 2-byte UTF-8\n if (point < 0x800) {\n result.push((point >> 6) | 192);\n result.push((point & 63) | 128);\n continue\n }\n\n // 3-byte UTF-8\n if (point < 0xD800 || (point >= 0xE000 && point < 0x10000)) {\n result.push((point >> 12) | 224);\n result.push(((point >> 6) & 63) | 128);\n result.push((point & 63) | 128);\n continue\n }\n\n // 4-byte UTF-8\n if (point >= 0x10000 && point <= 0x10FFFF) {\n result.push((point >> 18) | 240);\n result.push(((point >> 12) & 63) | 128);\n result.push(((point >> 6) & 63) | 128);\n result.push((point & 63) | 128);\n continue\n }\n\n // Invalid character\n result.push(0xEF, 0xBF, 0xBD);\n }\n\n return new Uint8Array(result).buffer\n };\n\n function ByteData (data) {\n this.mode = mode.BYTE;\n if (typeof (data) === 'string') {\n data = encodeUtf8(data);\n }\n this.data = new Uint8Array(data);\n }\n\n ByteData.getBitsLength = function getBitsLength (length) {\n return length * 8\n };\n\n ByteData.prototype.getLength = function getLength () {\n return this.data.length\n };\n\n ByteData.prototype.getBitsLength = function getBitsLength () {\n return ByteData.getBitsLength(this.data.length)\n };\n\n ByteData.prototype.write = function (bitBuffer) {\n for (let i = 0, l = this.data.length; i < l; i++) {\n bitBuffer.put(this.data[i], 8);\n }\n };\n\n var byteData = ByteData;\n\n function KanjiData (data) {\n this.mode = mode.KANJI;\n this.data = data;\n }\n\n KanjiData.getBitsLength = function getBitsLength (length) {\n return length * 13\n };\n\n KanjiData.prototype.getLength = function getLength () {\n return this.data.length\n };\n\n KanjiData.prototype.getBitsLength = function getBitsLength () {\n return KanjiData.getBitsLength(this.data.length)\n };\n\n KanjiData.prototype.write = function (bitBuffer) {\n let i;\n\n // In the Shift JIS system, Kanji characters are represented by a two byte combination.\n // These byte values are shifted from the JIS X 0208 values.\n // JIS X 0208 gives details of the shift coded representation.\n for (i = 0; i < this.data.length; i++) {\n let value = utils.toSJIS(this.data[i]);\n\n // For characters with Shift JIS values from 0x8140 to 0x9FFC:\n if (value >= 0x8140 && value <= 0x9FFC) {\n // Subtract 0x8140 from Shift JIS value\n value -= 0x8140;\n\n // For characters with Shift JIS values from 0xE040 to 0xEBBF\n } else if (value >= 0xE040 && value <= 0xEBBF) {\n // Subtract 0xC140 from Shift JIS value\n value -= 0xC140;\n } else {\n throw new Error(\n 'Invalid SJIS character: ' + this.data[i] + '\\n' +\n 'Make sure your charset is UTF-8')\n }\n\n // Multiply most significant byte of result by 0xC0\n // and add least significant byte to product\n value = (((value >>> 8) & 0xff) * 0xC0) + (value & 0xff);\n\n // Convert result to a 13-bit binary string\n bitBuffer.put(value, 13);\n }\n };\n\n var kanjiData = KanjiData;\n\n var dijkstra_1 = createCommonjsModule(function (module) {\n\n /******************************************************************************\n * Created 2008-08-19.\n *\n * Dijkstra path-finding functions. Adapted from the Dijkstar Python project.\n *\n * Copyright (C) 2008\n * Wyatt Baldwin \n * All rights reserved\n *\n * Licensed under the MIT license.\n *\n * http://www.opensource.org/licenses/mit-license.php\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *****************************************************************************/\n var dijkstra = {\n single_source_shortest_paths: function(graph, s, d) {\n // Predecessor map for each node that has been encountered.\n // node ID => predecessor node ID\n var predecessors = {};\n\n // Costs of shortest paths from s to all nodes encountered.\n // node ID => cost\n var costs = {};\n costs[s] = 0;\n\n // Costs of shortest paths from s to all nodes encountered; differs from\n // `costs` in that it provides easy access to the node that currently has\n // the known shortest path from s.\n // XXX: Do we actually need both `costs` and `open`?\n var open = dijkstra.PriorityQueue.make();\n open.push(s, 0);\n\n var closest,\n u, v,\n cost_of_s_to_u,\n adjacent_nodes,\n cost_of_e,\n cost_of_s_to_u_plus_cost_of_e,\n cost_of_s_to_v,\n first_visit;\n while (!open.empty()) {\n // In the nodes remaining in graph that have a known cost from s,\n // find the node, u, that currently has the shortest path from s.\n closest = open.pop();\n u = closest.value;\n cost_of_s_to_u = closest.cost;\n\n // Get nodes adjacent to u...\n adjacent_nodes = graph[u] || {};\n\n // ...and explore the edges that connect u to those nodes, updating\n // the cost of the shortest paths to any or all of those nodes as\n // necessary. v is the node across the current edge from u.\n for (v in adjacent_nodes) {\n if (adjacent_nodes.hasOwnProperty(v)) {\n // Get the cost of the edge running from u to v.\n cost_of_e = adjacent_nodes[v];\n\n // Cost of s to u plus the cost of u to v across e--this is *a*\n // cost from s to v that may or may not be less than the current\n // known cost to v.\n cost_of_s_to_u_plus_cost_of_e = cost_of_s_to_u + cost_of_e;\n\n // If we haven't visited v yet OR if the current known cost from s to\n // v is greater than the new cost we just found (cost of s to u plus\n // cost of u to v across e), update v's cost in the cost list and\n // update v's predecessor in the predecessor list (it's now u).\n cost_of_s_to_v = costs[v];\n first_visit = (typeof costs[v] === 'undefined');\n if (first_visit || cost_of_s_to_v > cost_of_s_to_u_plus_cost_of_e) {\n costs[v] = cost_of_s_to_u_plus_cost_of_e;\n open.push(v, cost_of_s_to_u_plus_cost_of_e);\n predecessors[v] = u;\n }\n }\n }\n }\n\n if (typeof d !== 'undefined' && typeof costs[d] === 'undefined') {\n var msg = ['Could not find a path from ', s, ' to ', d, '.'].join('');\n throw new Error(msg);\n }\n\n return predecessors;\n },\n\n extract_shortest_path_from_predecessor_list: function(predecessors, d) {\n var nodes = [];\n var u = d;\n var predecessor;\n while (u) {\n nodes.push(u);\n predecessor = predecessors[u];\n u = predecessors[u];\n }\n nodes.reverse();\n return nodes;\n },\n\n find_path: function(graph, s, d) {\n var predecessors = dijkstra.single_source_shortest_paths(graph, s, d);\n return dijkstra.extract_shortest_path_from_predecessor_list(\n predecessors, d);\n },\n\n /**\n * A very naive priority queue implementation.\n */\n PriorityQueue: {\n make: function (opts) {\n var T = dijkstra.PriorityQueue,\n t = {},\n key;\n opts = opts || {};\n for (key in T) {\n if (T.hasOwnProperty(key)) {\n t[key] = T[key];\n }\n }\n t.queue = [];\n t.sorter = opts.sorter || T.default_sorter;\n return t;\n },\n\n default_sorter: function (a, b) {\n return a.cost - b.cost;\n },\n\n /**\n * Add a new item to the queue and ensure the highest priority element\n * is at the front of the queue.\n */\n push: function (value, cost) {\n var item = {value: value, cost: cost};\n this.queue.push(item);\n this.queue.sort(this.sorter);\n },\n\n /**\n * Return the highest priority element in the queue.\n */\n pop: function () {\n return this.queue.shift();\n },\n\n empty: function () {\n return this.queue.length === 0;\n }\n }\n };\n\n\n // node.js module exports\n {\n module.exports = dijkstra;\n }\n });\n\n var segments = createCommonjsModule(function (module, exports) {\n /**\n * Returns UTF8 byte length\n *\n * @param {String} str Input string\n * @return {Number} Number of byte\n */\n function getStringByteLength (str) {\n return unescape(encodeURIComponent(str)).length\n }\n\n /**\n * Get a list of segments of the specified mode\n * from a string\n *\n * @param {Mode} mode Segment mode\n * @param {String} str String to process\n * @return {Array} Array of object with segments data\n */\n function getSegments (regex, mode, str) {\n const segments = [];\n let result;\n\n while ((result = regex.exec(str)) !== null) {\n segments.push({\n data: result[0],\n index: result.index,\n mode: mode,\n length: result[0].length\n });\n }\n\n return segments\n }\n\n /**\n * Extracts a series of segments with the appropriate\n * modes from a string\n *\n * @param {String} dataStr Input string\n * @return {Array} Array of object with segments data\n */\n function getSegmentsFromString (dataStr) {\n const numSegs = getSegments(regex.NUMERIC, mode.NUMERIC, dataStr);\n const alphaNumSegs = getSegments(regex.ALPHANUMERIC, mode.ALPHANUMERIC, dataStr);\n let byteSegs;\n let kanjiSegs;\n\n if (utils.isKanjiModeEnabled()) {\n byteSegs = getSegments(regex.BYTE, mode.BYTE, dataStr);\n kanjiSegs = getSegments(regex.KANJI, mode.KANJI, dataStr);\n } else {\n byteSegs = getSegments(regex.BYTE_KANJI, mode.BYTE, dataStr);\n kanjiSegs = [];\n }\n\n const segs = numSegs.concat(alphaNumSegs, byteSegs, kanjiSegs);\n\n return segs\n .sort(function (s1, s2) {\n return s1.index - s2.index\n })\n .map(function (obj) {\n return {\n data: obj.data,\n mode: obj.mode,\n length: obj.length\n }\n })\n }\n\n /**\n * Returns how many bits are needed to encode a string of\n * specified length with the specified mode\n *\n * @param {Number} length String length\n * @param {Mode} mode Segment mode\n * @return {Number} Bit length\n */\n function getSegmentBitsLength (length, mode$1) {\n switch (mode$1) {\n case mode.NUMERIC:\n return numericData.getBitsLength(length)\n case mode.ALPHANUMERIC:\n return alphanumericData.getBitsLength(length)\n case mode.KANJI:\n return kanjiData.getBitsLength(length)\n case mode.BYTE:\n return byteData.getBitsLength(length)\n }\n }\n\n /**\n * Merges adjacent segments which have the same mode\n *\n * @param {Array} segs Array of object with segments data\n * @return {Array} Array of object with segments data\n */\n function mergeSegments (segs) {\n return segs.reduce(function (acc, curr) {\n const prevSeg = acc.length - 1 >= 0 ? acc[acc.length - 1] : null;\n if (prevSeg && prevSeg.mode === curr.mode) {\n acc[acc.length - 1].data += curr.data;\n return acc\n }\n\n acc.push(curr);\n return acc\n }, [])\n }\n\n /**\n * Generates a list of all possible nodes combination which\n * will be used to build a segments graph.\n *\n * Nodes are divided by groups. Each group will contain a list of all the modes\n * in which is possible to encode the given text.\n *\n * For example the text '12345' can be encoded as Numeric, Alphanumeric or Byte.\n * The group for '12345' will contain then 3 objects, one for each\n * possible encoding mode.\n *\n * Each node represents a possible segment.\n *\n * @param {Array} segs Array of object with segments data\n * @return {Array} Array of object with segments data\n */\n function buildNodes (segs) {\n const nodes = [];\n for (let i = 0; i < segs.length; i++) {\n const seg = segs[i];\n\n switch (seg.mode) {\n case mode.NUMERIC:\n nodes.push([seg,\n { data: seg.data, mode: mode.ALPHANUMERIC, length: seg.length },\n { data: seg.data, mode: mode.BYTE, length: seg.length }\n ]);\n break\n case mode.ALPHANUMERIC:\n nodes.push([seg,\n { data: seg.data, mode: mode.BYTE, length: seg.length }\n ]);\n break\n case mode.KANJI:\n nodes.push([seg,\n { data: seg.data, mode: mode.BYTE, length: getStringByteLength(seg.data) }\n ]);\n break\n case mode.BYTE:\n nodes.push([\n { data: seg.data, mode: mode.BYTE, length: getStringByteLength(seg.data) }\n ]);\n }\n }\n\n return nodes\n }\n\n /**\n * Builds a graph from a list of nodes.\n * All segments in each node group will be connected with all the segments of\n * the next group and so on.\n *\n * At each connection will be assigned a weight depending on the\n * segment's byte length.\n *\n * @param {Array} nodes Array of object with segments data\n * @param {Number} version QR Code version\n * @return {Object} Graph of all possible segments\n */\n function buildGraph (nodes, version) {\n const table = {};\n const graph = { start: {} };\n let prevNodeIds = ['start'];\n\n for (let i = 0; i < nodes.length; i++) {\n const nodeGroup = nodes[i];\n const currentNodeIds = [];\n\n for (let j = 0; j < nodeGroup.length; j++) {\n const node = nodeGroup[j];\n const key = '' + i + j;\n\n currentNodeIds.push(key);\n table[key] = { node: node, lastCount: 0 };\n graph[key] = {};\n\n for (let n = 0; n < prevNodeIds.length; n++) {\n const prevNodeId = prevNodeIds[n];\n\n if (table[prevNodeId] && table[prevNodeId].node.mode === node.mode) {\n graph[prevNodeId][key] =\n getSegmentBitsLength(table[prevNodeId].lastCount + node.length, node.mode) -\n getSegmentBitsLength(table[prevNodeId].lastCount, node.mode);\n\n table[prevNodeId].lastCount += node.length;\n } else {\n if (table[prevNodeId]) table[prevNodeId].lastCount = node.length;\n\n graph[prevNodeId][key] = getSegmentBitsLength(node.length, node.mode) +\n 4 + mode.getCharCountIndicator(node.mode, version); // switch cost\n }\n }\n }\n\n prevNodeIds = currentNodeIds;\n }\n\n for (let n = 0; n < prevNodeIds.length; n++) {\n graph[prevNodeIds[n]].end = 0;\n }\n\n return { map: graph, table: table }\n }\n\n /**\n * Builds a segment from a specified data and mode.\n * If a mode is not specified, the more suitable will be used.\n *\n * @param {String} data Input data\n * @param {Mode | String} modesHint Data mode\n * @return {Segment} Segment\n */\n function buildSingleSegment (data, modesHint) {\n let mode$1;\n const bestMode = mode.getBestModeForData(data);\n\n mode$1 = mode.from(modesHint, bestMode);\n\n // Make sure data can be encoded\n if (mode$1 !== mode.BYTE && mode$1.bit < bestMode.bit) {\n throw new Error('\"' + data + '\"' +\n ' cannot be encoded with mode ' + mode.toString(mode$1) +\n '.\\n Suggested mode is: ' + mode.toString(bestMode))\n }\n\n // Use Mode.BYTE if Kanji support is disabled\n if (mode$1 === mode.KANJI && !utils.isKanjiModeEnabled()) {\n mode$1 = mode.BYTE;\n }\n\n switch (mode$1) {\n case mode.NUMERIC:\n return new numericData(data)\n\n case mode.ALPHANUMERIC:\n return new alphanumericData(data)\n\n case mode.KANJI:\n return new kanjiData(data)\n\n case mode.BYTE:\n return new byteData(data)\n }\n }\n\n /**\n * Builds a list of segments from an array.\n * Array can contain Strings or Objects with segment's info.\n *\n * For each item which is a string, will be generated a segment with the given\n * string and the more appropriate encoding mode.\n *\n * For each item which is an object, will be generated a segment with the given\n * data and mode.\n * Objects must contain at least the property \"data\".\n * If property \"mode\" is not present, the more suitable mode will be used.\n *\n * @param {Array} array Array of objects with segments data\n * @return {Array} Array of Segments\n */\n exports.fromArray = function fromArray (array) {\n return array.reduce(function (acc, seg) {\n if (typeof seg === 'string') {\n acc.push(buildSingleSegment(seg, null));\n } else if (seg.data) {\n acc.push(buildSingleSegment(seg.data, seg.mode));\n }\n\n return acc\n }, [])\n };\n\n /**\n * Builds an optimized sequence of segments from a string,\n * which will produce the shortest possible bitstream.\n *\n * @param {String} data Input string\n * @param {Number} version QR Code version\n * @return {Array} Array of segments\n */\n exports.fromString = function fromString (data, version) {\n const segs = getSegmentsFromString(data, utils.isKanjiModeEnabled());\n\n const nodes = buildNodes(segs);\n const graph = buildGraph(nodes, version);\n const path = dijkstra_1.find_path(graph.map, 'start', 'end');\n\n const optimizedSegs = [];\n for (let i = 1; i < path.length - 1; i++) {\n optimizedSegs.push(graph.table[path[i]].node);\n }\n\n return exports.fromArray(mergeSegments(optimizedSegs))\n };\n\n /**\n * Splits a string in various segments with the modes which\n * best represent their content.\n * The produced segments are far from being optimized.\n * The output of this function is only used to estimate a QR Code version\n * which may contain the data.\n *\n * @param {string} data Input string\n * @return {Array} Array of segments\n */\n exports.rawSplit = function rawSplit (data) {\n return exports.fromArray(\n getSegmentsFromString(data, utils.isKanjiModeEnabled())\n )\n };\n });\n\n /**\n * QRCode for JavaScript\n *\n * modified by Ryan Day for nodejs support\n * Copyright (c) 2011 Ryan Day\n *\n * Licensed under the MIT license:\n * http://www.opensource.org/licenses/mit-license.php\n *\n //---------------------------------------------------------------------\n // QRCode for JavaScript\n //\n // Copyright (c) 2009 Kazuhiko Arase\n //\n // URL: http://www.d-project.com/\n //\n // Licensed under the MIT license:\n // http://www.opensource.org/licenses/mit-license.php\n //\n // The word \"QR Code\" is registered trademark of\n // DENSO WAVE INCORPORATED\n // http://www.denso-wave.com/qrcode/faqpatent-e.html\n //\n //---------------------------------------------------------------------\n */\n\n /**\n * Add finder patterns bits to matrix\n *\n * @param {BitMatrix} matrix Modules matrix\n * @param {Number} version QR Code version\n */\n function setupFinderPattern (matrix, version) {\n const size = matrix.size;\n const pos = finderPattern.getPositions(version);\n\n for (let i = 0; i < pos.length; i++) {\n const row = pos[i][0];\n const col = pos[i][1];\n\n for (let r = -1; r <= 7; r++) {\n if (row + r <= -1 || size <= row + r) continue\n\n for (let c = -1; c <= 7; c++) {\n if (col + c <= -1 || size <= col + c) continue\n\n if ((r >= 0 && r <= 6 && (c === 0 || c === 6)) ||\n (c >= 0 && c <= 6 && (r === 0 || r === 6)) ||\n (r >= 2 && r <= 4 && c >= 2 && c <= 4)) {\n matrix.set(row + r, col + c, true, true);\n } else {\n matrix.set(row + r, col + c, false, true);\n }\n }\n }\n }\n }\n\n /**\n * Add timing pattern bits to matrix\n *\n * Note: this function must be called before {@link setupAlignmentPattern}\n *\n * @param {BitMatrix} matrix Modules matrix\n */\n function setupTimingPattern (matrix) {\n const size = matrix.size;\n\n for (let r = 8; r < size - 8; r++) {\n const value = r % 2 === 0;\n matrix.set(r, 6, value, true);\n matrix.set(6, r, value, true);\n }\n }\n\n /**\n * Add alignment patterns bits to matrix\n *\n * Note: this function must be called after {@link setupTimingPattern}\n *\n * @param {BitMatrix} matrix Modules matrix\n * @param {Number} version QR Code version\n */\n function setupAlignmentPattern (matrix, version) {\n const pos = alignmentPattern.getPositions(version);\n\n for (let i = 0; i < pos.length; i++) {\n const row = pos[i][0];\n const col = pos[i][1];\n\n for (let r = -2; r <= 2; r++) {\n for (let c = -2; c <= 2; c++) {\n if (r === -2 || r === 2 || c === -2 || c === 2 ||\n (r === 0 && c === 0)) {\n matrix.set(row + r, col + c, true, true);\n } else {\n matrix.set(row + r, col + c, false, true);\n }\n }\n }\n }\n }\n\n /**\n * Add version info bits to matrix\n *\n * @param {BitMatrix} matrix Modules matrix\n * @param {Number} version QR Code version\n */\n function setupVersionInfo (matrix, version$1) {\n const size = matrix.size;\n const bits = version.getEncodedBits(version$1);\n let row, col, mod;\n\n for (let i = 0; i < 18; i++) {\n row = Math.floor(i / 3);\n col = i % 3 + size - 8 - 3;\n mod = ((bits >> i) & 1) === 1;\n\n matrix.set(row, col, mod, true);\n matrix.set(col, row, mod, true);\n }\n }\n\n /**\n * Add format info bits to matrix\n *\n * @param {BitMatrix} matrix Modules matrix\n * @param {ErrorCorrectionLevel} errorCorrectionLevel Error correction level\n * @param {Number} maskPattern Mask pattern reference value\n */\n function setupFormatInfo (matrix, errorCorrectionLevel, maskPattern) {\n const size = matrix.size;\n const bits = formatInfo.getEncodedBits(errorCorrectionLevel, maskPattern);\n let i, mod;\n\n for (i = 0; i < 15; i++) {\n mod = ((bits >> i) & 1) === 1;\n\n // vertical\n if (i < 6) {\n matrix.set(i, 8, mod, true);\n } else if (i < 8) {\n matrix.set(i + 1, 8, mod, true);\n } else {\n matrix.set(size - 15 + i, 8, mod, true);\n }\n\n // horizontal\n if (i < 8) {\n matrix.set(8, size - i - 1, mod, true);\n } else if (i < 9) {\n matrix.set(8, 15 - i - 1 + 1, mod, true);\n } else {\n matrix.set(8, 15 - i - 1, mod, true);\n }\n }\n\n // fixed module\n matrix.set(size - 8, 8, 1, true);\n }\n\n /**\n * Add encoded data bits to matrix\n *\n * @param {BitMatrix} matrix Modules matrix\n * @param {Uint8Array} data Data codewords\n */\n function setupData (matrix, data) {\n const size = matrix.size;\n let inc = -1;\n let row = size - 1;\n let bitIndex = 7;\n let byteIndex = 0;\n\n for (let col = size - 1; col > 0; col -= 2) {\n if (col === 6) col--;\n\n while (true) {\n for (let c = 0; c < 2; c++) {\n if (!matrix.isReserved(row, col - c)) {\n let dark = false;\n\n if (byteIndex < data.length) {\n dark = (((data[byteIndex] >>> bitIndex) & 1) === 1);\n }\n\n matrix.set(row, col - c, dark);\n bitIndex--;\n\n if (bitIndex === -1) {\n byteIndex++;\n bitIndex = 7;\n }\n }\n }\n\n row += inc;\n\n if (row < 0 || size <= row) {\n row -= inc;\n inc = -inc;\n break\n }\n }\n }\n }\n\n /**\n * Create encoded codewords from data input\n *\n * @param {Number} version QR Code version\n * @param {ErrorCorrectionLevel} errorCorrectionLevel Error correction level\n * @param {ByteData} data Data input\n * @return {Uint8Array} Buffer containing encoded codewords\n */\n function createData (version, errorCorrectionLevel, segments) {\n // Prepare data buffer\n const buffer = new bitBuffer();\n\n segments.forEach(function (data) {\n // prefix data with mode indicator (4 bits)\n buffer.put(data.mode.bit, 4);\n\n // Prefix data with character count indicator.\n // The character count indicator is a string of bits that represents the\n // number of characters that are being encoded.\n // The character count indicator must be placed after the mode indicator\n // and must be a certain number of bits long, depending on the QR version\n // and data mode\n // @see {@link Mode.getCharCountIndicator}.\n buffer.put(data.getLength(), mode.getCharCountIndicator(data.mode, version));\n\n // add binary data sequence to buffer\n data.write(buffer);\n });\n\n // Calculate required number of bits\n const totalCodewords = utils.getSymbolTotalCodewords(version);\n const ecTotalCodewords = errorCorrectionCode.getTotalCodewordsCount(version, errorCorrectionLevel);\n const dataTotalCodewordsBits = (totalCodewords - ecTotalCodewords) * 8;\n\n // Add a terminator.\n // If the bit string is shorter than the total number of required bits,\n // a terminator of up to four 0s must be added to the right side of the string.\n // If the bit string is more than four bits shorter than the required number of bits,\n // add four 0s to the end.\n if (buffer.getLengthInBits() + 4 <= dataTotalCodewordsBits) {\n buffer.put(0, 4);\n }\n\n // If the bit string is fewer than four bits shorter, add only the number of 0s that\n // are needed to reach the required number of bits.\n\n // After adding the terminator, if the number of bits in the string is not a multiple of 8,\n // pad the string on the right with 0s to make the string's length a multiple of 8.\n while (buffer.getLengthInBits() % 8 !== 0) {\n buffer.putBit(0);\n }\n\n // Add pad bytes if the string is still shorter than the total number of required bits.\n // Extend the buffer to fill the data capacity of the symbol corresponding to\n // the Version and Error Correction Level by adding the Pad Codewords 11101100 (0xEC)\n // and 00010001 (0x11) alternately.\n const remainingByte = (dataTotalCodewordsBits - buffer.getLengthInBits()) / 8;\n for (let i = 0; i < remainingByte; i++) {\n buffer.put(i % 2 ? 0x11 : 0xEC, 8);\n }\n\n return createCodewords(buffer, version, errorCorrectionLevel)\n }\n\n /**\n * Encode input data with Reed-Solomon and return codewords with\n * relative error correction bits\n *\n * @param {BitBuffer} bitBuffer Data to encode\n * @param {Number} version QR Code version\n * @param {ErrorCorrectionLevel} errorCorrectionLevel Error correction level\n * @return {Uint8Array} Buffer containing encoded codewords\n */\n function createCodewords (bitBuffer, version, errorCorrectionLevel) {\n // Total codewords for this QR code version (Data + Error correction)\n const totalCodewords = utils.getSymbolTotalCodewords(version);\n\n // Total number of error correction codewords\n const ecTotalCodewords = errorCorrectionCode.getTotalCodewordsCount(version, errorCorrectionLevel);\n\n // Total number of data codewords\n const dataTotalCodewords = totalCodewords - ecTotalCodewords;\n\n // Total number of blocks\n const ecTotalBlocks = errorCorrectionCode.getBlocksCount(version, errorCorrectionLevel);\n\n // Calculate how many blocks each group should contain\n const blocksInGroup2 = totalCodewords % ecTotalBlocks;\n const blocksInGroup1 = ecTotalBlocks - blocksInGroup2;\n\n const totalCodewordsInGroup1 = Math.floor(totalCodewords / ecTotalBlocks);\n\n const dataCodewordsInGroup1 = Math.floor(dataTotalCodewords / ecTotalBlocks);\n const dataCodewordsInGroup2 = dataCodewordsInGroup1 + 1;\n\n // Number of EC codewords is the same for both groups\n const ecCount = totalCodewordsInGroup1 - dataCodewordsInGroup1;\n\n // Initialize a Reed-Solomon encoder with a generator polynomial of degree ecCount\n const rs = new reedSolomonEncoder(ecCount);\n\n let offset = 0;\n const dcData = new Array(ecTotalBlocks);\n const ecData = new Array(ecTotalBlocks);\n let maxDataSize = 0;\n const buffer = new Uint8Array(bitBuffer.buffer);\n\n // Divide the buffer into the required number of blocks\n for (let b = 0; b < ecTotalBlocks; b++) {\n const dataSize = b < blocksInGroup1 ? dataCodewordsInGroup1 : dataCodewordsInGroup2;\n\n // extract a block of data from buffer\n dcData[b] = buffer.slice(offset, offset + dataSize);\n\n // Calculate EC codewords for this data block\n ecData[b] = rs.encode(dcData[b]);\n\n offset += dataSize;\n maxDataSize = Math.max(maxDataSize, dataSize);\n }\n\n // Create final data\n // Interleave the data and error correction codewords from each block\n const data = new Uint8Array(totalCodewords);\n let index = 0;\n let i, r;\n\n // Add data codewords\n for (i = 0; i < maxDataSize; i++) {\n for (r = 0; r < ecTotalBlocks; r++) {\n if (i < dcData[r].length) {\n data[index++] = dcData[r][i];\n }\n }\n }\n\n // Apped EC codewords\n for (i = 0; i < ecCount; i++) {\n for (r = 0; r < ecTotalBlocks; r++) {\n data[index++] = ecData[r][i];\n }\n }\n\n return data\n }\n\n /**\n * Build QR Code symbol\n *\n * @param {String} data Input string\n * @param {Number} version QR Code version\n * @param {ErrorCorretionLevel} errorCorrectionLevel Error level\n * @param {MaskPattern} maskPattern Mask pattern\n * @return {Object} Object containing symbol data\n */\n function createSymbol (data, version$1, errorCorrectionLevel, maskPattern$1) {\n let segments$1;\n\n if (Array.isArray(data)) {\n segments$1 = segments.fromArray(data);\n } else if (typeof data === 'string') {\n let estimatedVersion = version$1;\n\n if (!estimatedVersion) {\n const rawSegments = segments.rawSplit(data);\n\n // Estimate best version that can contain raw splitted segments\n estimatedVersion = version.getBestVersionForData(rawSegments, errorCorrectionLevel);\n }\n\n // Build optimized segments\n // If estimated version is undefined, try with the highest version\n segments$1 = segments.fromString(data, estimatedVersion || 40);\n } else {\n throw new Error('Invalid data')\n }\n\n // Get the min version that can contain data\n const bestVersion = version.getBestVersionForData(segments$1, errorCorrectionLevel);\n\n // If no version is found, data cannot be stored\n if (!bestVersion) {\n throw new Error('The amount of data is too big to be stored in a QR Code')\n }\n\n // If not specified, use min version as default\n if (!version$1) {\n version$1 = bestVersion;\n\n // Check if the specified version can contain the data\n } else if (version$1 < bestVersion) {\n throw new Error('\\n' +\n 'The chosen QR Code version cannot contain this amount of data.\\n' +\n 'Minimum version required to store current data is: ' + bestVersion + '.\\n'\n )\n }\n\n const dataBits = createData(version$1, errorCorrectionLevel, segments$1);\n\n // Allocate matrix buffer\n const moduleCount = utils.getSymbolSize(version$1);\n const modules = new bitMatrix(moduleCount);\n\n // Add function modules\n setupFinderPattern(modules, version$1);\n setupTimingPattern(modules);\n setupAlignmentPattern(modules, version$1);\n\n // Add temporary dummy bits for format info just to set them as reserved.\n // This is needed to prevent these bits from being masked by {@link MaskPattern.applyMask}\n // since the masking operation must be performed only on the encoding region.\n // These blocks will be replaced with correct values later in code.\n setupFormatInfo(modules, errorCorrectionLevel, 0);\n\n if (version$1 >= 7) {\n setupVersionInfo(modules, version$1);\n }\n\n // Add data codewords\n setupData(modules, dataBits);\n\n if (isNaN(maskPattern$1)) {\n // Find best mask pattern\n maskPattern$1 = maskPattern.getBestMask(modules,\n setupFormatInfo.bind(null, modules, errorCorrectionLevel));\n }\n\n // Apply mask pattern\n maskPattern.applyMask(maskPattern$1, modules);\n\n // Replace format info bits with correct values\n setupFormatInfo(modules, errorCorrectionLevel, maskPattern$1);\n\n return {\n modules: modules,\n version: version$1,\n errorCorrectionLevel: errorCorrectionLevel,\n maskPattern: maskPattern$1,\n segments: segments$1\n }\n }\n\n /**\n * QR Code\n *\n * @param {String | Array} data Input data\n * @param {Object} options Optional configurations\n * @param {Number} options.version QR Code version\n * @param {String} options.errorCorrectionLevel Error correction level\n * @param {Function} options.toSJISFunc Helper func to convert utf8 to sjis\n */\n var create = function create (data, options) {\n if (typeof data === 'undefined' || data === '') {\n throw new Error('No input text')\n }\n\n let errorCorrectionLevel$1 = errorCorrectionLevel.M;\n let version$1;\n let mask;\n\n if (typeof options !== 'undefined') {\n // Use higher error correction level as default\n errorCorrectionLevel$1 = errorCorrectionLevel.from(options.errorCorrectionLevel, errorCorrectionLevel.M);\n version$1 = version.from(options.version);\n mask = maskPattern.from(options.maskPattern);\n\n if (options.toSJISFunc) {\n utils.setToSJISFunction(options.toSJISFunc);\n }\n }\n\n return createSymbol(data, version$1, errorCorrectionLevel$1, mask)\n };\n\n var qrcode = {\n \tcreate: create\n };\n\n var utils$1 = createCommonjsModule(function (module, exports) {\n function hex2rgba (hex) {\n if (typeof hex === 'number') {\n hex = hex.toString();\n }\n\n if (typeof hex !== 'string') {\n throw new Error('Color should be defined as hex string')\n }\n\n let hexCode = hex.slice().replace('#', '').split('');\n if (hexCode.length < 3 || hexCode.length === 5 || hexCode.length > 8) {\n throw new Error('Invalid hex color: ' + hex)\n }\n\n // Convert from short to long form (fff -> ffffff)\n if (hexCode.length === 3 || hexCode.length === 4) {\n hexCode = Array.prototype.concat.apply([], hexCode.map(function (c) {\n return [c, c]\n }));\n }\n\n // Add default alpha value\n if (hexCode.length === 6) hexCode.push('F', 'F');\n\n const hexValue = parseInt(hexCode.join(''), 16);\n\n return {\n r: (hexValue >> 24) & 255,\n g: (hexValue >> 16) & 255,\n b: (hexValue >> 8) & 255,\n a: hexValue & 255,\n hex: '#' + hexCode.slice(0, 6).join('')\n }\n }\n\n exports.getOptions = function getOptions (options) {\n if (!options) options = {};\n if (!options.color) options.color = {};\n\n const margin = typeof options.margin === 'undefined' ||\n options.margin === null ||\n options.margin < 0\n ? 4\n : options.margin;\n\n const width = options.width && options.width >= 21 ? options.width : undefined;\n const scale = options.scale || 4;\n\n return {\n width: width,\n scale: width ? 4 : scale,\n margin: margin,\n color: {\n dark: hex2rgba(options.color.dark || '#000000ff'),\n light: hex2rgba(options.color.light || '#ffffffff')\n },\n type: options.type,\n rendererOpts: options.rendererOpts || {}\n }\n };\n\n exports.getScale = function getScale (qrSize, opts) {\n return opts.width && opts.width >= qrSize + opts.margin * 2\n ? opts.width / (qrSize + opts.margin * 2)\n : opts.scale\n };\n\n exports.getImageWidth = function getImageWidth (qrSize, opts) {\n const scale = exports.getScale(qrSize, opts);\n return Math.floor((qrSize + opts.margin * 2) * scale)\n };\n\n exports.qrToImageData = function qrToImageData (imgData, qr, opts) {\n const size = qr.modules.size;\n const data = qr.modules.data;\n const scale = exports.getScale(size, opts);\n const symbolSize = Math.floor((size + opts.margin * 2) * scale);\n const scaledMargin = opts.margin * scale;\n const palette = [opts.color.light, opts.color.dark];\n\n for (let i = 0; i < symbolSize; i++) {\n for (let j = 0; j < symbolSize; j++) {\n let posDst = (i * symbolSize + j) * 4;\n let pxColor = opts.color.light;\n\n if (i >= scaledMargin && j >= scaledMargin &&\n i < symbolSize - scaledMargin && j < symbolSize - scaledMargin) {\n const iSrc = Math.floor((i - scaledMargin) / scale);\n const jSrc = Math.floor((j - scaledMargin) / scale);\n pxColor = palette[data[iSrc * size + jSrc] ? 1 : 0];\n }\n\n imgData[posDst++] = pxColor.r;\n imgData[posDst++] = pxColor.g;\n imgData[posDst++] = pxColor.b;\n imgData[posDst] = pxColor.a;\n }\n }\n };\n });\n\n var canvas = createCommonjsModule(function (module, exports) {\n function clearCanvas (ctx, canvas, size) {\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n\n if (!canvas.style) canvas.style = {};\n canvas.height = size;\n canvas.width = size;\n canvas.style.height = size + 'px';\n canvas.style.width = size + 'px';\n }\n\n function getCanvasElement () {\n try {\n return document.createElement('canvas')\n } catch (e) {\n throw new Error('You need to specify a canvas element')\n }\n }\n\n exports.render = function render (qrData, canvas, options) {\n let opts = options;\n let canvasEl = canvas;\n\n if (typeof opts === 'undefined' && (!canvas || !canvas.getContext)) {\n opts = canvas;\n canvas = undefined;\n }\n\n if (!canvas) {\n canvasEl = getCanvasElement();\n }\n\n opts = utils$1.getOptions(opts);\n const size = utils$1.getImageWidth(qrData.modules.size, opts);\n\n const ctx = canvasEl.getContext('2d');\n const image = ctx.createImageData(size, size);\n utils$1.qrToImageData(image.data, qrData, opts);\n\n clearCanvas(ctx, canvasEl, size);\n ctx.putImageData(image, 0, 0);\n\n return canvasEl\n };\n\n exports.renderToDataURL = function renderToDataURL (qrData, canvas, options) {\n let opts = options;\n\n if (typeof opts === 'undefined' && (!canvas || !canvas.getContext)) {\n opts = canvas;\n canvas = undefined;\n }\n\n if (!opts) opts = {};\n\n const canvasEl = exports.render(qrData, canvas, opts);\n\n const type = opts.type || 'image/png';\n const rendererOpts = opts.rendererOpts || {};\n\n return canvasEl.toDataURL(type, rendererOpts.quality)\n };\n });\n\n function getColorAttrib (color, attrib) {\n const alpha = color.a / 255;\n const str = attrib + '=\"' + color.hex + '\"';\n\n return alpha < 1\n ? str + ' ' + attrib + '-opacity=\"' + alpha.toFixed(2).slice(1) + '\"'\n : str\n }\n\n function svgCmd (cmd, x, y) {\n let str = cmd + x;\n if (typeof y !== 'undefined') str += ' ' + y;\n\n return str\n }\n\n function qrToPath (data, size, margin) {\n let path = '';\n let moveBy = 0;\n let newRow = false;\n let lineLength = 0;\n\n for (let i = 0; i < data.length; i++) {\n const col = Math.floor(i % size);\n const row = Math.floor(i / size);\n\n if (!col && !newRow) newRow = true;\n\n if (data[i]) {\n lineLength++;\n\n if (!(i > 0 && col > 0 && data[i - 1])) {\n path += newRow\n ? svgCmd('M', col + margin, 0.5 + row + margin)\n : svgCmd('m', moveBy, 0);\n\n moveBy = 0;\n newRow = false;\n }\n\n if (!(col + 1 < size && data[i + 1])) {\n path += svgCmd('h', lineLength);\n lineLength = 0;\n }\n } else {\n moveBy++;\n }\n }\n\n return path\n }\n\n var render = function render (qrData, options, cb) {\n const opts = utils$1.getOptions(options);\n const size = qrData.modules.size;\n const data = qrData.modules.data;\n const qrcodesize = size + opts.margin * 2;\n\n const bg = !opts.color.light.a\n ? ''\n : '';\n\n const path =\n '';\n\n const viewBox = 'viewBox=\"' + '0 0 ' + qrcodesize + ' ' + qrcodesize + '\"';\n\n const width = !opts.width ? '' : 'width=\"' + opts.width + '\" height=\"' + opts.width + '\" ';\n\n const svgTag = '' + bg + path + '\\n';\n\n if (typeof cb === 'function') {\n cb(null, svgTag);\n }\n\n return svgTag\n };\n\n var svgTag = {\n \trender: render\n };\n\n function renderCanvas (renderFunc, canvas, text, opts, cb) {\n const args = [].slice.call(arguments, 1);\n const argsNum = args.length;\n const isLastArgCb = typeof args[argsNum - 1] === 'function';\n\n if (!isLastArgCb && !canPromise()) {\n throw new Error('Callback required as last argument')\n }\n\n if (isLastArgCb) {\n if (argsNum < 2) {\n throw new Error('Too few arguments provided')\n }\n\n if (argsNum === 2) {\n cb = text;\n text = canvas;\n canvas = opts = undefined;\n } else if (argsNum === 3) {\n if (canvas.getContext && typeof cb === 'undefined') {\n cb = opts;\n opts = undefined;\n } else {\n cb = opts;\n opts = text;\n text = canvas;\n canvas = undefined;\n }\n }\n } else {\n if (argsNum < 1) {\n throw new Error('Too few arguments provided')\n }\n\n if (argsNum === 1) {\n text = canvas;\n canvas = opts = undefined;\n } else if (argsNum === 2 && !canvas.getContext) {\n opts = text;\n text = canvas;\n canvas = undefined;\n }\n\n return new Promise(function (resolve, reject) {\n try {\n const data = qrcode.create(text, opts);\n resolve(renderFunc(data, canvas, opts));\n } catch (e) {\n reject(e);\n }\n })\n }\n\n try {\n const data = qrcode.create(text, opts);\n cb(null, renderFunc(data, canvas, opts));\n } catch (e) {\n cb(e);\n }\n }\n\n var create$1 = qrcode.create;\n var toCanvas = renderCanvas.bind(null, canvas.render);\n var toDataURL = renderCanvas.bind(null, canvas.renderToDataURL);\n\n // only svg for now.\n var toString_1 = renderCanvas.bind(null, function (data, _, opts) {\n return svgTag.render(data, opts)\n });\n\n var browser = {\n \tcreate: create$1,\n \ttoCanvas: toCanvas,\n \ttoDataURL: toDataURL,\n \ttoString: toString_1\n };\n\n /**\n * Class to help with node & page binding.\n * The selected node is what kbTree binds to, and is also what configuratorController\n * sets when trying to set the active page through code or the rules. The selected page\n * is what drives which page is shown and is not necessarily the same thing.\n * There is a special case for nested configurators when they only have one visible page\n * (with no visible children of the page) that we try to show the nested configurator as\n * one node (instead of a node for the configurator, and another child node for the page).\n */\n var SelectedBinding = /** @class */ (function () {\n function SelectedBinding() {\n this.pageChanged = new enums.PropertyChangedEvent();\n }\n Object.defineProperty(SelectedBinding.prototype, \"page\", {\n get: function () {\n return this._page;\n },\n enumerable: false,\n configurable: true\n });\n /**\n * private routine to set the page as consumers should all set the node\n * @param newPage\n */\n SelectedBinding.prototype.setPage = function (newPage) {\n var oldPage = this._page;\n var changed = oldPage !== newPage;\n this._page = newPage;\n if (changed)\n this.pageChanged.trigger({ oldValue: oldPage, newValue: newPage, property: 'page' });\n };\n Object.defineProperty(SelectedBinding.prototype, \"node\", {\n get: function () {\n return this._node;\n },\n set: function (newNode) {\n if (newNode instanceof enums.Configurator) {\n var firstPage = newNode.pages.find(function (p) { return p.visible; });\n if (firstPage) {\n newNode = firstPage;\n }\n }\n var oldNode = this._node;\n var changed = oldNode !== newNode;\n this._node = newNode;\n if (changed) {\n var parentConfig = newNode instanceof enums.Configurator ? newNode : newNode.$parentConfigurator;\n if (this.isSingleNode(parentConfig)) {\n this._node = parentConfig;\n this.setPage(newNode);\n }\n else {\n this._node = newNode;\n this.setPage(newNode);\n }\n }\n },\n enumerable: false,\n configurable: true\n });\n /**\n * if this is the special case where a nested config is shown as a single node because it has only one visible page\n * @param tab\n */\n SelectedBinding.prototype.isSingleNode = function (tab) {\n return (tab.$parent &&\n !tab.pages.some(function (p) { return p.pages.some(function (p2) { return p2.visible; }) || p.configurators.length > 0; }) &&\n tab.pages.filter(function (p) { return p.visible; }).length == 1);\n };\n return SelectedBinding;\n }());\n var ConfiguratorRuleArgs = /** @class */ (function () {\n function ConfiguratorRuleArgs(ctrl) {\n this.ctrl = ctrl;\n this.activeUrl = window.location.href;\n this.isMobile = ctrl.$rootScope.windowWidth < _tools.Utils.MOBILE_WIDTH;\n this.windowWidth = ctrl.$rootScope.windowWidth;\n this.windowHeight = ctrl.$rootScope.windowHeight;\n }\n ConfiguratorRuleArgs.prototype.getTables = function (args) {\n var _this = this;\n return new _rules.KPromise(args.ids.map(function (tid) { return _this.ctrl.helper.tableArraysDb[tid]; }));\n };\n ConfiguratorRuleArgs.prototype.upload = function () {\n var _this = this;\n return this.ctrl.uploadService.promptUserToChooseFile().then(function (file) {\n return _this.ctrl.$scope.upload(file, null);\n });\n };\n ConfiguratorRuleArgs.prototype.sendMessage = function (msg) {\n // send message to embed consumer\n _tools.Utils.sendMessageToParent(msg);\n this.ctrl.sfdcService.sendMessage(msg);\n };\n ConfiguratorRuleArgs.prototype.callSafeFunction = function (obj) {\n return this.ctrl.api.safeFunctions.run(obj.safeFunctionId, obj.parameters, this.ctrl.$rootScope.contentTracker);\n };\n ConfiguratorRuleArgs.prototype.startIntervalFunction = function (id, timeSeconds) {\n return this.ctrl.runContinuousAsyncRule(id, timeSeconds);\n };\n ConfiguratorRuleArgs.prototype.stopIntervalFunction = function (id) {\n this.ctrl.cancelScheduledRule(id);\n };\n ConfiguratorRuleArgs.prototype.startTimeoutFunction = function (func, timeSeconds) {\n this.ctrl.runTimeoutRule(func, timeSeconds);\n };\n ConfiguratorRuleArgs.prototype.convertCurrency = function (obj) {\n return this.ctrl.kbService.fxConvertAsync(obj.amount, obj.currencyCode);\n };\n ConfiguratorRuleArgs.prototype.generateNumber = function (args) {\n return this.ctrl.api.generators.next(args.generatorId, this.ctrl.$rootScope.contentTracker);\n };\n ConfiguratorRuleArgs.prototype.selectPage = function (page) {\n var _this = this;\n this.ctrl.$timeout(function () { return _this.ctrl.selectNode(page); });\n };\n ConfiguratorRuleArgs.prototype.navigateToElement = function (elem) {\n this.ctrl.navigateToElement(elem);\n };\n ConfiguratorRuleArgs.prototype.nextPage = function () {\n var _this = this;\n this.ctrl.$timeout(function () { return _this.ctrl.$scope.nextPage(); });\n };\n ConfiguratorRuleArgs.prototype.backPage = function () {\n var _this = this;\n this.ctrl.$timeout(function () { return _this.ctrl.$scope.backPage(); });\n };\n ConfiguratorRuleArgs.prototype.runSceneAction = function (name) {\n return this.ctrl.runSceneAction(this.configurator, name);\n };\n ConfiguratorRuleArgs.prototype.callSceneFunction = function (args) {\n var sv = this.ctrl.$scope.activeSceneViewer;\n if (sv && sv instanceof Kb3dViewer) {\n return sv.runSceneFunction(args, this.configurator).then(function (r) { return r.parameters.returnValue; });\n }\n console.warn(\"Scene function \".concat(args.name, \" was called but a scene is not loaded.\"));\n return Promise.resolve(null);\n };\n ConfiguratorRuleArgs.prototype.setScene = function (args) {\n return this.ctrl.setScene(this.configurator, args.idScene);\n };\n ConfiguratorRuleArgs.prototype.runNamingRule = function () {\n return this.ctrl.helper.runRuleTypeAsync(this.configurator, enums.eRuleType.naming);\n };\n ConfiguratorRuleArgs.prototype.addNestedConfigurator = function (idProduct, idParent, name, fields) {\n // this call already came from a rule, so we don't need to run the oncePerRuleCycle here\n return this.ctrl.addNestedConfig(idProduct, this.configurator.$manager.get(idParent), false, name, fields);\n };\n ConfiguratorRuleArgs.prototype.copyNestedConfigurator = function (nested, idParent, name) {\n var sourceConfig = nested;\n if (angular.isString(nested)) {\n sourceConfig = this.configurator.$manager.getByName(nested, false);\n }\n return this.ctrl.copyNestedConfig(sourceConfig, this.configurator.$manager.get(idParent), false, name);\n };\n ConfiguratorRuleArgs.prototype.setNumberOfNestedConfigurators = function (idProduct, idParent, n) {\n return this.ctrl.setNumberOfNestedConfigs(idProduct, this.configurator.$manager.get(idParent), n);\n };\n ConfiguratorRuleArgs.prototype.removeNestedConfigurator = function (nested) {\n var nestedConfig = nested;\n if (angular.isString(nested)) {\n nestedConfig = this.configurator.$manager.getByName(nested, false);\n }\n return this.ctrl.removeNestedConfig(nestedConfig);\n };\n ConfiguratorRuleArgs.prototype.showPriceDetails = function () {\n this.ctrl.$scope.showPricing();\n };\n ConfiguratorRuleArgs.prototype.alert = function (args) {\n this.ctrl.dialogService.alert(args);\n };\n ConfiguratorRuleArgs.prototype.getOptionFilterSource = function (idOptionFilter, fromConfigurator) {\n fromConfigurator = fromConfigurator || this.configurator;\n var f = fromConfigurator.$manager.get(idOptionFilter);\n return new _rules.KPromise(f ? f.$source : []);\n };\n ConfiguratorRuleArgs.prototype.setLayoutSetting = function (id, value) {\n if (!this.configurator.isNested()) {\n //nested configurators should not be able to override the root's layout settings\n var s = this.layoutConfig.$manager.getByIdOrName(id, true);\n var origValue = s.value;\n s.value = value;\n if (origValue != s.value) {\n this.layoutConfig.$layoutSettingsDirty = true;\n }\n }\n };\n ConfiguratorRuleArgs.prototype.getLayoutSetting = function (id) {\n var s = this.layoutConfig.$manager.getByIdOrName(id, true);\n return s.value;\n };\n ConfiguratorRuleArgs.prototype.toggleFullscreen = function () {\n this.ctrl.$rootScope.toggleFullscreen();\n };\n ConfiguratorRuleArgs.prototype.runConfiguredProduct = function (configProd) {\n //run the configured product after this rule has ended\n this.ctrl.runConfiguredProduct(this.configurator, configProd);\n };\n return ConfiguratorRuleArgs;\n }());\n var SvgRuleArgs = /** @class */ (function (_super) {\n __extends(SvgRuleArgs, _super);\n function SvgRuleArgs() {\n return _super !== null && _super.apply(this, arguments) || this;\n }\n return SvgRuleArgs;\n }(ConfiguratorRuleArgs));\n var ConfiguratorController = /** @class */ (function (_super) {\n __extends(ConfiguratorController, _super);\n function ConfiguratorController($scope, $q, $location, $state, $stateParams, $http, $rootScope, $window, $compile, $injector, dialogService, $timeout, $interval, $filter, drawerService, ruleService, uploadService, authService, quoteService, promiseTracker, api, themeService, sfdcService, kbService, telemetryService, interactionService, ocLazyLoad) {\n var _this = _super.call(this) || this;\n _this.$scope = $scope;\n _this.$q = $q;\n _this.$location = $location;\n _this.$state = $state;\n _this.$stateParams = $stateParams;\n _this.$http = $http;\n _this.$rootScope = $rootScope;\n _this.$window = $window;\n _this.$compile = $compile;\n _this.$injector = $injector;\n _this.dialogService = dialogService;\n _this.$timeout = $timeout;\n _this.$interval = $interval;\n _this.$filter = $filter;\n _this.drawerService = drawerService;\n _this.ruleService = ruleService;\n _this.uploadService = uploadService;\n _this.authService = authService;\n _this.quoteService = quoteService;\n _this.promiseTracker = promiseTracker;\n _this.api = api;\n _this.themeService = themeService;\n _this.sfdcService = sfdcService;\n _this.kbService = kbService;\n _this.telemetryService = telemetryService;\n _this.interactionService = interactionService;\n _this.ocLazyLoad = ocLazyLoad;\n _this.runAsyncRule = true;\n // a cache of scene sessions in case the configurator loads the same scene multiple times\n _this.sceneDb = {};\n _this.productDb = {};\n _this.translationDb = {};\n _this.sceneViewerDb = {}; // holds a map of sceneViewer's to the scene id\n _this.loading = true; // whether the configurator is currently loading\n _this.runningRules = {};\n _this.model = {};\n _this.configuratorLoadedDeferred = _this.$q.defer();\n _this.$scope.layoutLoaded = false;\n _this.$rootScope.contentTracker.addPromise(_this.configuratorLoadedDeferred.promise);\n var isScene = ($scope.isScene = $state.current.name == 'scene');\n var queryString = $location.search();\n $scope.isTest = false;\n if ($state.current.data) {\n $scope.isEdit = $state.current.data.viewType == enums.eViewType.edit;\n $scope.isNew = $state.current.data.viewType == enums.eViewType.new;\n $scope.isView = $state.current.data.viewType == enums.eViewType.view;\n $scope.isTest = $state.current.data.isTest == true;\n }\n if ($scope.isTest) {\n _this.drawerService.setHelpUrl('Configurators');\n }\n else {\n _this.drawerService.setHelpUrl(null);\n }\n // setup binding to handle selected page and node\n $scope.selected = new SelectedBinding();\n $scope.pricingTracker = promiseTracker();\n $scope.priceDialogTracker = promiseTracker();\n $scope.arLoading = promiseTracker();\n $scope.showSpinnerPricing = true;\n // $scope.showConfigHeader = (queryString.showconfigheader != \"false\");\n // $scope.showFields = (queryString.showfields != \"false\");\n $scope.showMove = queryString.showmove == 'true';\n $scope.isEmbed = _tools.Utils.isDefined(queryString.embedded);\n $scope.embedFields = queryString['fields'] ? JSON.parse(queryString['fields']) : null;\n $scope.embedLayoutSettings = queryString['layoutsettings'] ? JSON.parse(queryString['layoutsettings']) : null;\n $scope.embedParameters = queryString['parameters'] ? JSON.parse(queryString['parameters']) : null;\n $scope.embedCurrency = queryString['currency'];\n $scope.deferLoadedRule = queryString['deferLoadedRule'] == 'true';\n $scope.isKinetic = !!queryString['kineticCompany'];\n // only allow the embed currency if it's a defined company currency\n if (!_this.$rootScope.companyCurrencies.some(function (c) { return c.currency == $scope.embedCurrency; })) {\n $scope.embedCurrency = null;\n }\n $scope.actionsVisible = true;\n $scope.absUrl = $location.absUrl();\n $scope.isReadOnly = false;\n if ($scope.isEmbed) {\n $rootScope.hideDrawer = queryString.showdrawer != 'true';\n $rootScope.transparentBackground = queryString.transparentbackground == 'true';\n }\n if (_tools.Utils.isDefined(queryString.showheader) && queryString.showheader == 'false') {\n $rootScope.hideHeader = true;\n }\n _this.requestId = queryString.requestid;\n _this.helper = new ConfiguratorHelper({\n $http: _this.$http,\n $q: _this.$q,\n api: _this.api,\n dialogService: _this.dialogService,\n ruleService: _this.ruleService,\n tracker: _this.$rootScope.contentTracker,\n $rootScope: _this.$rootScope,\n getRuleArgs: function (c, f) { return _this.getRuleArgs(c, f); },\n showErrors: function () { return _this.showErrors(); },\n });\n $scope.translateKbo = function (o, prop) {\n if (o) {\n if (_this.$rootScope.companySettings.defaultLanguage != _this.$rootScope.clientLanguage) {\n var parentConfig = o instanceof enums.Configurator ? o : o.$parentConfigurator;\n var configDb = _this.translationDb[parentConfig.idProduct || parentConfig.idScene];\n if (configDb && configDb.hasOwnProperty(o.id) && configDb[o.id].hasOwnProperty(prop)) {\n return configDb[o.id][prop];\n }\n }\n var realProp = prop == 'name' ? '$label' : prop;\n return o[realProp];\n }\n return '';\n };\n _this.getConfigurator().then(function (rootConfig) {\n if (rootConfig == null)\n return;\n _this.rootConfig = $scope.config = $scope.tab = rootConfig;\n _this.interactionService.record(_this.rootConfig.idProduct);\n $scope.selected.pageChanged.add(function (args) {\n // run the pageChanged rule\n var pageParentConfig = args.newValue.$parentConfigurator;\n var pageChangedArgs = _this.getRuleArgs(pageParentConfig);\n pageChangedArgs.selectedPage = args.newValue;\n if (window.location.href.includes('ar=true')) {\n _this.enterArModal();\n }\n _this.trackConfigPageView(pageChangedArgs.selectedPage);\n _this.queueRule(function () {\n return _this.helper\n .runRuleTypeAsync(pageParentConfig, enums.eRuleType.pageChanged, pageChangedArgs)\n .then(function (r) {\n // make sure all nodes are expanded\n if (args.newValue) {\n var parent_1 = args.newValue;\n while (parent_1) {\n parent_1.$expanded = true;\n parent_1 = parent_1.$parent;\n }\n }\n if (!_this.loading && pageParentConfig.getRuleJs(enums.eRuleType.pageChanged)) {\n return _this.runRuleCycleUnit(pageParentConfig, null).then(function () {\n return _this.oncePerCycleRule();\n });\n }\n else {\n // refresh viewer so we can change scenes for\n // nested configurators with scenes that aren't nesting\n _this.getCurrentConfigForViewerAndSetViewerMode(); //set the viewermode before layout rule so it can show/hide the viewer accordingly\n return _this.runLayoutRule(_this.$scope.config, _this.getRuleArgs(_this.$scope.config)).then(function () {\n return _this.refreshViewer(true).then(function () {\n // even if not running the value rule, we still need to\n // update the nodes for the next / back buttons\n _this.calculateNodes();\n });\n });\n }\n });\n });\n });\n $scope.testBuild = function (build) {\n _this.runSubmitRule().then(function () {\n _this.helper.runRuleTypeAsync(_this.rootConfig, enums.eRuleType.naming);\n var buildRuleArgs = _this.getRuleArgs(_this.rootConfig);\n buildRuleArgs.build = build;\n buildRuleArgs.quote = {\n name: 'Test Quote',\n id: 1,\n ownedBy: _this.$rootScope.user.id,\n owner: _this.$rootScope.user.firstName + ' ' + _this.$rootScope.user.lastName,\n description: '',\n currency: 'USD',\n };\n buildRuleArgs.quoteProduct = {\n isConfigured: true,\n id: 1,\n qty: 1,\n priceObject: _this.$scope.priceObject,\n name: _this.rootConfig.name,\n description: _this.rootConfig.description,\n shortDescription: _this.rootConfig.shortDescription,\n };\n var displayDialog = function (queueId) {\n var dialogScope = $rootScope.$new();\n dialogScope.model = {\n testBuildName: _this.rootConfig.name + ' ' + build.name + ' Test Build',\n idQueue: queueId,\n };\n dialogScope.validation = {};\n api.queues.search().then(function (r) { return (dialogScope.queues = r); });\n dialogService.dialog({\n template: Dirs.view('dialog-test-build'),\n scope: dialogScope,\n buttons: [\n new enums.InputDialogButton(loc.ok, _tools.icons.success, function (args) {\n if (!dialogScope.model.testBuildName) {\n dialogScope.validation['testBuildName'] = 'Name is required';\n args.close = false;\n return;\n }\n if (dialogScope.model.testBuildName.length > 400) {\n dialogScope.validation['testBuildName'] =\n 'Name must be less than 400 characters';\n args.close = false;\n return;\n }\n _this.api.testBuilds\n .insert({\n idBuildType: build.idBuildType,\n idProduct: parseInt($state.params.id, 10),\n name: dialogScope.model.testBuildName,\n idQueue: dialogScope.model.idQueue,\n configuredProduct: _this.rootConfig.getConfiguredProduct(),\n cloudBuild: build.cloudBuild,\n priceObject: _this.$scope.priceObject,\n }, _this.$rootScope.contentTracker)\n .then(function (testBuild) {\n dialogService.confirm('Your configurator is building ' +\n build.name +\n ' outputs. Would you like to go to the test build page?', function () {\n $state.go('kb.admin.testBuild', { id: testBuild.id });\n });\n });\n }),\n new enums.InputDialogButton(loc.cancel, _tools.icons.cancel, function (args) { }),\n ],\n });\n };\n try {\n _this.helper\n .runRuleContainerAsync(build.ruleContainers.find(function (rc) { return rc.ruleType == enums.eRuleType.beforeBuild; }), buildRuleArgs)\n .then(function (result) {\n var queueId = result.parameters.build.idQueue;\n displayDialog(queueId);\n }, function () {\n // We'll want to display the dialog even if this rule fails,\n // since it's possible it's due to functionality that's only available in server-side rules.\n displayDialog(build.idQueue);\n });\n }\n catch (e) {\n // We'll want to display the dialog even if this rule fails, since it's possible it's due to\n // functionality that's only available in server-side rules.\n displayDialog(build.idQueue);\n }\n });\n };\n $scope.getSubmitButtonText = function () {\n return _this.$scope.config.submitButtonText ? _this.$scope.config.submitButtonText : loc.addtoquote;\n };\n $scope.getSubmitAndStayButtonText = function () {\n return _this.$scope.config.submitAndStayButtonText\n ? _this.$scope.config.submitAndStayButtonText\n : loc.saveandstay;\n };\n $scope.getGenerateQrCodeText = function () {\n return _this.$scope.config.generateQrCodeText\n ? _this.$scope.config.generateQrCodeText\n : loc.generateqrcode;\n };\n $scope.submitButtonClick = function () {\n if ($scope.isEmbed) {\n _tools.Utils.sendMessageToParent({ name: 'submit', data: {} });\n }\n else {\n return _this.submit();\n }\n };\n $scope.runFixThis = function (field, fix) {\n return _this.queueRule(function () {\n return new _rules.KPromise(fix.fix())\n .then(function () { return _this.runRuleCycleUnit(field.$parentConfigurator, null); })\n .then(function () { return _this.oncePerCycleRule(); });\n });\n };\n var getTargetElementId = function ($event) {\n var el = $event.target;\n var elementId = el.id;\n while (!elementId && el) {\n if (el.tagName == 'svg')\n break;\n elementId = el.id;\n el = el.parentElement;\n }\n return elementId;\n };\n var getSvgArgs = function (svgViewer, $event, $originalStartEvent) {\n if ($originalStartEvent === void 0) { $originalStartEvent = null; }\n var c = svgViewer.$parentConfigurator;\n var args = _this.getRuleArgs(c);\n args.elementId = getTargetElementId($event);\n args.mouseX = $event.offsetX;\n args.mouseY = $event.offsetY;\n args.commitDrag = false;\n if ($originalStartEvent) {\n args.originMouseX = $originalStartEvent.offsetX;\n args.originMouseY = $originalStartEvent.offsetY;\n args.originElementId = getTargetElementId($originalStartEvent);\n }\n return args;\n };\n $scope.runSvgAction = function (svgViewer, $event) {\n var rc = svgViewer.ruleContainers.find(function (rc) { return rc.ruleType == enums.eRuleType.svgViewer; });\n if (rc) {\n var args = getSvgArgs(svgViewer, $event);\n return _this.queueEventRule(svgViewer.$parentConfigurator, rc, args);\n }\n };\n var originalDragStartEvent = null;\n var svgViewerShouldEnablePanAfterDrag = false;\n $scope.svgDragStart = function (svgViewer, $event) {\n var rc = svgViewer.ruleContainers.find(function (r) { return r.ruleType == enums.eRuleType.dragStart; });\n if (rc) {\n var args = getSvgArgs(svgViewer, $event, originalDragStartEvent);\n return _this.helper.runRuleContainerAsync(rc, args).then(function (result) {\n if (!result.hasError && result.parameters.commitDrag) {\n originalDragStartEvent = $event;\n svgViewerShouldEnablePanAfterDrag = !svgViewer.disablePan;\n svgViewer.disablePan = true;\n }\n });\n }\n };\n $scope.svgDragMove = function (svgViewer, $event) {\n if (originalDragStartEvent) {\n var rc = svgViewer.ruleContainers.find(function (r) { return r.ruleType == enums.eRuleType.dragMove; });\n if (rc) {\n var args = getSvgArgs(svgViewer, $event, originalDragStartEvent);\n return _this.helper.runRuleContainerAsync(rc, args).then(function () { return $scope.$digest(); });\n }\n }\n };\n $scope.svgDragEnd = function (svgViewer, $event) {\n if (originalDragStartEvent) {\n var rc = svgViewer.ruleContainers.find(function (r) { return r.ruleType == enums.eRuleType.dragEnd; });\n if (rc) {\n var args = getSvgArgs(svgViewer, $event, originalDragStartEvent);\n originalDragStartEvent = null;\n svgViewer.disablePan = !svgViewerShouldEnablePanAfterDrag;\n return _this.queueEventRule(svgViewer.$parentConfigurator, rc, args);\n }\n }\n };\n $scope.runFieldAction = function (field) {\n if (isScene) {\n return _this.$scope.activeSceneViewer && _this.$scope.activeSceneViewer.runFieldAction(field);\n }\n else {\n return _this.queueEventRule(field.$parentConfigurator, field, _this.getRuleArgs(field.$parentConfigurator));\n }\n };\n $scope.runAction = function (action) {\n if (isScene) {\n return _this.queueRule(function () { return _this.runSceneAction(_this.rootConfig, action.name); });\n }\n else {\n return _this.queueEventRule(action.$parentConfigurator, action, _this.getRuleArgs(action.$parentConfigurator));\n }\n };\n $scope.fieldValueChange = function (field) {\n if (!_this.loading) {\n return _this.queueRule(function () {\n return _this.helper\n .runRuleContainerAsync(field)\n .then(function () { return _this.runRuleCycleUnit(field.$parentConfigurator, field); })\n .then(function () { return _this.oncePerCycleRule(); });\n });\n }\n };\n $scope.fieldTouched = function (field) {\n field.hasBeenTouched = true;\n if (field.$parentConfigurator.validationTiming == enums.eValidationTiming.onTouched) {\n _this.rootConfig.isValid(); //recalculate root as the field might be in a nested set, which is in a page, etc.\n }\n };\n $scope.tabChanged = function (oldTab, newTab, tabControl) {\n if (!_this.loading) {\n var c = tabControl.$parentConfigurator;\n var args = _this.getRuleArgs(c);\n args.oldTab = c.$manager.getByName(oldTab, false);\n args.newTab = c.$manager.getByName(newTab, false);\n args.tabControl = tabControl;\n var origNumberOfNesteds = c.getNestedConfigurators().length;\n return _this.queueEventRuleType(c, enums.eRuleType.tabChanged, args);\n }\n };\n $scope.keydown = function (k) {\n if (!(k.target instanceof HTMLInputElement ||\n k.target instanceof HTMLTextAreaElement ||\n (k.target instanceof HTMLElement && k.target.classList.contains('kb-no-keyboard-rule')))) {\n var keyArgs = {\n event: k,\n key: k.key,\n keyCode: k.keyCode,\n altKey: k.altKey,\n ctrlKey: k.ctrlKey || k.metaKey,\n shiftKey: k.shiftKey,\n repeat: k.repeat,\n };\n var ruleArgs = _this.getRuleArgs($scope.config);\n ruleArgs.keyArgs = keyArgs;\n return _this.queueEventRuleType($scope.config, enums.eRuleType.keyboard, ruleArgs);\n }\n };\n $scope.expanderChanged = function (expander) {\n if (!_this.loading) {\n var c = expander.$parentConfigurator;\n var args = _this.getRuleArgs(c);\n args.expander = expander;\n var origNumberOfNesteds = c.getNestedConfigurators().length;\n return _this.queueEventRuleType(c, enums.eRuleType.expanderChanged, args);\n }\n };\n $scope.nestedTabSelected = function (oldTab, nestedName, nestedSet) {\n var newTab = nestedSet.$parentConfigurator.$manager.getByName(nestedName, false);\n return $scope.nestedSetSelected(nestedSet, newTab);\n };\n $scope.nestedSetSelected = function (nestedSet, nested) {\n if (!_this.loading) {\n var c = nested;\n var args = _this.getRuleArgs(nestedSet.$parentConfigurator);\n args.nested = c;\n var parentConfig = c.$parentConfigurator;\n return _this.queueEventRule(nestedSet.$parentConfigurator, nestedSet, args);\n }\n };\n $scope.togglePages = function (show) {\n var changed = $scope.showPages != show;\n $scope.showPages = show;\n if (changed) {\n $scope.resizeScene();\n _this.refreshDrawer();\n }\n };\n $scope.resizeScene = function () {\n if ($scope.activeSceneViewer) {\n $timeout(function () {\n $timeout(function () {\n $scope.activeSceneViewer.resize();\n $scope.activeSceneViewer.refreshElementParent();\n });\n }, 0);\n }\n };\n $scope.pageClick = function (e, page) {\n e.stopPropagation();\n $scope.togglePages(true);\n };\n $scope.nextPage = function () {\n if (_this.$scope.nextNode)\n _this.selectNode(_this.$scope.nextNode);\n };\n $scope.backPage = function () {\n if (_this.$scope.backNode)\n _this.selectNode(_this.$scope.backNode);\n };\n $scope.nestedClick = function (e, nested) {\n e.stopPropagation();\n _this.selectNode(nested);\n // var firstPage = nested.pages.find(p => p.visible);\n // if (firstPage) {\n // this.selectNode(firstPage);\n // }\n };\n $scope.hasChildren = function (tab) {\n if (tab instanceof enums.Configurator && $scope.selected.isSingleNode(tab)) {\n return tab.configurators.length > 0;\n }\n else {\n return tab.pages.some(function (p) { return p.visible; }) || tab.configurators.length > 0;\n }\n };\n var thisCtrl = _this;\n $scope.upload = function (file, field) {\n var uploadOptions = {\n convertPdfToImage: field.convertUploadPdfToImage,\n };\n return thisCtrl.uploadService.uploadConfiguredProductFile(file, uploadOptions).then(function (uuid) {\n var uploadValue = field.value;\n uploadValue.path = uuid;\n field.$parentConfigurator.$fieldsDirty = true;\n field.$parentConfigurator.$fieldsDirtyForSceneRules = true;\n // clear the asset id in case there was an old file there that was just\n // replaced to make sure the new file is uploaded to the scene\n uploadValue.assetId = null;\n if (thisCtrl.$scope.activeSceneViewer && thisCtrl.$scope.activeSceneViewer.scene.external) {\n var sceneUploadPromise = thisCtrl.$scope.activeSceneViewer.importUploadFieldImage(field.$parentConfigurator, field, file);\n thisCtrl.$rootScope.contentTracker.addPromise(sceneUploadPromise);\n return sceneUploadPromise;\n }\n });\n };\n $scope.uploadCleared = function (field) {\n field.$parentConfigurator.$fieldsDirty = true;\n field.$parentConfigurator.$fieldsDirtyForSceneRules = true;\n };\n $scope.getCurrency = function () {\n // if there is a quote, then that overrides everything\n if ($scope.parentQuote) {\n return $scope.parentQuote.currency;\n }\n else if (quoteService.quote) {\n return quoteService.quote.currency;\n }\n else {\n //if this is an sfdc cpq, use the incoming currency if provided\n if (_this.$scope.sfdcHasCurrency) {\n //console.log(this.$rootScope.context.sfdcConvertCurrency ?? 'convert currency not set');\n return _this.$scope.sfdcCurrency;\n }\n // if we are in an embed, and the embed currency was specified, then use it\n if (_this.$scope.isEmbed && _this.$scope.embedCurrency) {\n return _this.$scope.embedCurrency;\n }\n else {\n // just use the default company currency\n return _this.$rootScope.companySettings.currency;\n }\n }\n };\n $scope.showPricing = function (item) {\n if (_this.lastPricingPromise) {\n _this.$scope.priceDialogTracker.addPromise(_this.lastPricingPromise);\n _this.lastPricingPromise.then(function () {\n var dialogScope = $scope.$new();\n dialogScope.itemsInView = [];\n dialogScope.item = item || $scope.priceObject;\n _this.addLevelsToPricing(dialogScope.item);\n dialogScope.flat =\n dialogScope.item.items && !dialogScope.item.items.some(function (i) { return i.items.length > 0; });\n dialogScope.getCurrency = $scope.getCurrency;\n dialogScope.title = (item ? item.sku : _this.rootConfig.name) + ' Pricing';\n dialogScope.getColumnValue = function (col, item) {\n var val = col.systemColumn\n ? item[col.name.toCamelCase()]\n : item.columns[col.name.toCamelCase()];\n var format = col.format;\n if (col.name.isEqual('discount')) {\n if ((item.useRollup && item.items && item.items.length) || item.discountType == '$') {\n val = item.totalDiscount;\n format = enums.eFormatType.currency;\n }\n else {\n format = enums.eFormatType.percentage;\n }\n }\n if (col.type == enums.eColumnType.number) {\n var minPrecision = Number(col.formatMinPrecision);\n var precision = Number(col.precision);\n if (format == enums.eFormatType.currency && precision === 2 && minPrecision === 2) {\n val = $filter('fxConvert')(val, $scope.getCurrency());\n }\n else {\n if (format == enums.eFormatType.currency) {\n val = kbService.fxConvert(val, $scope.getCurrency());\n }\n val = Number(val).format({\n formatType: format,\n minPrecision: minPrecision,\n maxPrecision: precision,\n currency: $scope.getCurrency(),\n decimalSeparator: col.formatDecimalSeparator,\n thousandsSeparator: col.formatThousandsSeparator,\n prefix: col.formatPrefix,\n suffix: col.formatSuffix,\n });\n }\n }\n return val;\n };\n dialogScope.openItem = function (nestedItem) {\n // $scope.showPricing(nestedItem)\n nestedItem.$expanded = !nestedItem.$expanded;\n };\n dialogScope.smartColorStyle = function (level) {\n var background = new _tools.Color(_this.themeService.getActiveTheme().background);\n if (level) {\n if (background.isDark()) {\n background = _tools.Color.lighten(background.getOriginalInput(), level * 6);\n }\n else {\n background = _tools.Color.darken(background.getOriginalInput(), level * 6);\n }\n }\n var color = background.isDark() ? 'white' : 'black';\n return 'background: ' + background.toRgbString() + '; color: ' + color + ';';\n };\n dialogScope.infiniteScroll = function () {\n var totalCount = $scope.priceObject.items.length;\n var currCount = dialogScope.itemsInView.length;\n if (totalCount > currCount) {\n var i = currCount;\n if (i < 0)\n i = 0;\n dialogScope.itemsInView.pushArray($scope.priceObject.items.slice(i, i + 50));\n }\n };\n dialogScope.infiniteScroll();\n dialogService.dialog({\n fullHeight: true,\n template: Dirs.view('dialog-price-object'),\n scope: dialogScope,\n buttons: [\n new enums.DialogButton(loc.close, _tools.icons.cancel, function (args) {\n if ($scope.isEmbed) {\n _tools.Utils.sendMessageToParent({ name: 'pricingDetailsClosed', data: {} });\n }\n }),\n ],\n });\n if ($scope.isEmbed) {\n _tools.Utils.sendMessageToParent({ name: 'pricingDetailsShown', data: {} });\n }\n });\n }\n };\n $scope.addNestedConfigClick = function (e, parent) {\n // if the parent only has one type of referenced configurator, then we add it\n // if more than 1 ref config, then let control pass to the dropdown\n var parentConfig = parent instanceof enums.Configurator ? parent : parent.$parentConfigurator;\n var entries = $scope.userCanAddToDb[parentConfig.idProduct][parent.id];\n if (entries && entries.length == 1) {\n e.stopPropagation();\n return $scope.addNestedConfig(entries[0].id, parent, true);\n }\n return new _rules.KPromise(null);\n };\n $scope.addNestedConfig = function (idNested, parent, addedByUser, name) {\n return _this.addNestedConfig(idNested, parent, addedByUser, name).then(function (config) {\n return _this.runRuleCycleUnit(config.$parentConfigurator, null).then(function () {\n return _this.oncePerCycleRule().then(function () { return config; });\n });\n });\n };\n $scope.copyNestedConfig = function (source) {\n var sourceConfig = source instanceof enums.Configurator ? source : source.$parentConfigurator;\n return _this.copyNestedConfig(sourceConfig, sourceConfig.$parent, true).then(function (target) {\n return _this.nestedRunBottomsUp(target, function (c) { return _this.runRuleCycleUnit(c, null); });\n });\n };\n $scope.removeNestedConfig = function (nested) {\n // might be a page or configurator passed in. If it's a page,\n // it's the page's parent configurator that needs to be deleted\n if (nested instanceof enums.Page || nested instanceof enums.NestedSet)\n nested = nested.$parentConfigurator;\n _this.dialogService.confirm(\"Are you sure you want to remove the item '\" + nested.name + \"'?\", function () {\n return _this.removeNestedConfig(nested).then(function () {\n var parentConfig = nested.$parent instanceof enums.Configurator\n ? nested.$parent\n : nested.$parent.$parentConfigurator;\n return _this.runRuleCycleUnit(parentConfig, null).then(function () { return _this.oncePerCycleRule(); });\n });\n });\n };\n $scope.autoCompleteQuery = function (query, field) {\n return _this.helper.autoCompleteQuery(query, field);\n };\n $scope.autoCompleteGetLabel = function (value, field) {\n return _this.helper.autoCompleteGetLabel(value, field);\n };\n $scope.togglePageSlide = function (show) {\n $scope.pageSlideVisible = show;\n };\n $scope.selectNode = function (node) {\n _this.selectNode(node);\n };\n // $scope.render = () => {\n // if (this.$scope.sceneViewer) {\n // var promise = this.$scope.sceneViewer.render().then((url) => {\n // this.rootConfig.viewerMediaPath = url;\n // });\n // this.dialogService && this.dialogService.alert({\n // msg: \"Your rendering is being processed\",\n // persist: false,\n // timeShown: 1,\n // promise: promise\n // });\n // return promise;\n // }\n // return $q.when(null);\n // };\n // when used in an iframe, we need to catch messages posted from the outside world to respond\n var messageHandler = function (event) {\n var msg = event.data;\n if (msg) {\n var data_1 = msg.data;\n if (msg.name) {\n var messageName = msg.name.toLowerCase();\n if (messageName == 'setfields') {\n $scope.$apply(function () {\n _this.queueRule(function () {\n $scope.config.setFields(data_1);\n return _this.runRuleCycleUnit($scope.config, null)\n .then(function () { return _this.oncePerCycleRule(); })\n .then(function () {\n _tools.Utils.sendMessageToParent({\n name: 'configuratorMessage',\n data: {},\n correspondenceId: msg.correspondenceId,\n });\n });\n });\n });\n }\n else if (messageName == 'getfields') {\n var response_1 = {};\n _this.rootConfig.getFields().forEach(function (f) {\n response_1[f.name] = f.value;\n });\n _tools.Utils.sendMessageToParent({\n name: 'configuratorMessage',\n data: response_1,\n correspondenceId: msg.correspondenceId,\n });\n }\n else if (messageName == 'setconfiguredproduct') {\n $scope.$apply(function () {\n return _this.runConfiguredProduct(rootConfig, data_1).then(function () {\n if ($scope.deferLoadedRule && _this.readyToStart) {\n _this.model = { configuredProduct: data_1 };\n _this.readyToStart.resolve();\n _this.readyToStart = null;\n }\n _tools.Utils.sendMessageToParent({\n name: 'configuratorMessage',\n data: {},\n correspondenceId: msg.correspondenceId,\n });\n });\n });\n }\n else if (messageName == 'getconfiguredproduct') {\n _this.queueRule(function () {\n _tools.Utils.sendMessageToParent({\n name: 'configuratorMessage',\n data: _this.rootConfig.getConfiguredProduct(),\n correspondenceId: msg.correspondenceId,\n });\n return new _rules.KPromise(null);\n });\n }\n else if (messageName == 'runaction') {\n $scope.$apply(function () {\n var action = _this.rootConfig.actions.find(function (a) { return a.name.isEqual(msg.data); });\n $scope.runAction(action).then(function () {\n _tools.Utils.sendMessageToParent({\n name: 'configuratorMessage',\n data: {},\n correspondenceId: msg.correspondenceId,\n });\n });\n });\n }\n else if (messageName == 'saveproductandsubmit') {\n $scope.$apply(function () {\n // clear out current quote first\n quoteService.quote = null;\n _this.submit(true)\n .then(function () {\n return _this.api.quotes\n .submit(_this.quoteService.quote, _this.$rootScope.contentTracker)\n .then(function (q) {\n // clear out the active quote again\n quoteService.quote = null;\n return q;\n });\n })\n .then(function (q) {\n _tools.Utils.sendMessageToParent({\n name: 'configuratorMessage',\n data: q,\n correspondenceId: msg.correspondenceId,\n });\n });\n });\n }\n else if (messageName == 'saveproduct') {\n $scope.$apply(function () {\n _this.submit(true).then(function () {\n _tools.Utils.sendMessageToParent({\n name: 'configuratorMessage',\n data: _this.quoteService.quote,\n correspondenceId: msg.correspondenceId,\n });\n });\n });\n }\n else if (messageName == 'snapshot') {\n if ($scope.activeSceneViewer) {\n $scope.activeSceneViewer.snapshot(msg.data).then(function (result) {\n if (result) {\n _tools.Utils.sendMessageToParent({\n name: 'configuratorMessage',\n data: result,\n correspondenceId: msg.correspondenceId,\n });\n }\n });\n }\n }\n else if (messageName == 'runsubmitrule') {\n $scope.$apply(function () {\n _this.runSubmitRule().then(function () {\n _tools.Utils.sendMessageToParent({\n name: 'configuratorMessage',\n data: {},\n correspondenceId: msg.correspondenceId,\n });\n });\n });\n }\n else if (messageName == 'getprice') {\n $scope.$apply(function () {\n _this.runPricing().then(function () {\n _tools.Utils.sendMessageToParent({\n name: 'configuratorMessage',\n data: _this.rootConfig.priceObject,\n correspondenceId: msg.correspondenceId,\n });\n });\n });\n }\n else {\n var messageArgs = jQuery.extend(_this.getRuleArgs(_this.rootConfig), { message: msg });\n if (_this.rootConfig.hasRule(enums.eRuleType.message)) {\n return _this.queueEventRuleType(_this.rootConfig, enums.eRuleType.message, messageArgs).then(function () {\n _this.$scope.$digest();\n });\n }\n }\n }\n }\n };\n $window.addEventListener('message', messageHandler);\n $window.addEventListener('keydown', $scope.keydown);\n $scope.$on('$destroy', function () {\n $window.removeEventListener('message', messageHandler);\n $window.removeEventListener('keydown', $scope.keydown);\n });\n // $scope.$watchCollection(\"config.actions\", () => {\n // $timeout(() => this.resizeActionBar(), 1);\n // });\n // this.resizeActionBar = Utils.throttle(() => {\n // // $timeout(() => {\n // let moreButtonsVisible = false;\n // //let $actionBar = $(\".kb-config__action-bar\");\n // let $header = $(\".kb-config__header\");\n // let $moreButton = $(\".kb-config__more-actions\");\n // // get more button width\n // $moreButton.css(\"display\", \"inline-block\");\n // let moreButtonWidth = $moreButton.outerWidth();\n // $moreButton.css(\"display\", \"\");\n // let available = $header.outerWidth() / 2 - moreButtonWidth; //$actionBar.outerWidth() - moreButtonWidth;\n // let taken: number = 0;\n // this.$scope.config.actions.forEach(action => {\n // if (action.visible) {\n // let $action = $(\"#action-\" + action.id);\n // let $moreAction = $(\"#action-more-\" + action.id);\n // // temporarily set the action to be visible even if it's\n // // currently hidden because it's in the more menu\n // $action.css(\"display\", \"inline-block\");\n // let actionWidth = $action.outerWidth();\n // taken += actionWidth;\n // let visibleInMore = (taken > available);\n // if (visibleInMore) moreButtonsVisible = true;\n // $action.css(\"display\", visibleInMore ? \"none\" : \"\");\n // $moreAction.css(\"display\", visibleInMore ? \"\" : \"none\");\n // }\n // });\n // $moreButton.css(\"display\", moreButtonsVisible ? \"\" : \"none\");\n // // });\n // }, 100);\n _this.runResizeRule = _tools.Utils.debounce(function () {\n // run the resize rule of the configurator\n if (_this.$scope.config.getRuleJs(enums.eRuleType.resize) || _this.$scope.config.getRuleJs(enums.eRuleType.layout)) {\n var args_1 = _this.getRuleArgs(_this.$scope.config);\n _this.helper.runRuleTypeAsync(_this.$scope.config, enums.eRuleType.resize, args_1).then(function () {\n if (_this.$scope.config.hasRule(enums.eRuleType.layout)) {\n _this.runLayoutRule(_this.$scope.config, args_1).then(function () {\n _this.$scope.$digest();\n });\n }\n });\n }\n }, 100);\n $(window).resize(function () {\n $timeout(function () {\n _this.runResizeRule();\n //this.resizeActionBar();\n _this.refreshDrawer();\n }, 1);\n });\n // get pricing columns if relevant\n if (_this.hasPricing()) {\n _this.api.priceColumns.getPriceColumnsForUser().then(function (r) {\n _this.$scope.priceColumns = r;\n _this.$scope.priceColumnDb = {};\n _this.$scope.priceColumns.forEach(function (pc) { return (_this.$scope.priceColumnDb[pc.name] = pc); });\n _this.$scope.pricePrecision = _this.$scope.priceColumns.find(function (pc) { return pc.id == 14; } /* <-- ExtNetPrice --> */).precision;\n });\n }\n _this.drawerService.pageTitle = _this.rootConfig.name;\n _this.drawerService.pageType = loc.configurator;\n _this.drawerService.pageIcon = _tools.icons.configurator;\n _this.drawerService.showHelp = false;\n if (_this.$scope.isTest) {\n if (rootConfig.builds.length) {\n var drawers_1 = [];\n rootConfig.builds.forEach(function (b) {\n drawers_1.push({\n icon: _tools.icons.gear,\n label: b.name,\n command: function () {\n $scope.testBuild(b);\n },\n });\n });\n drawerService.addDrawer(_tools.icons.test, loc.testbuild, function () { }, true, drawers_1);\n }\n drawerService.addDrawer(_tools.icons.test, loc.testpricing, function () {\n var pricingArgs = jQuery.extend(_this.getRuleArgs(_this.rootConfig), {\n priceObject: {\n items: [],\n fields: {},\n },\n quoteCreator: _this.$rootScope.user,\n quoteOwner: _this.$rootScope.user,\n });\n return _this.helper.runRuleTypeAsync(_this.rootConfig, enums.eRuleType.pricing, pricingArgs);\n });\n drawerService.addDrawer(_tools.icons.name, loc.runnamingrule, function () {\n _this.helper.runRuleTypeAsync(_this.rootConfig, enums.eRuleType.naming);\n });\n }\n // this.drawerViewer = drawerService.addDrawer(icons.threeD, loc.threedview, () => {\n // this.$scope.togglePages(false);\n // });\n // this.drawerViewer.classes = \"visible-xs\";\n // this.drawerOptions = drawerService.addDrawer(icons.group, loc.options, () => {\n // this.$scope.togglePages(true);\n // });\n // this.drawerOptions.classes = \"visible-xs\";\n // this.drawerPricing = drawerService.addDrawer(icons.column, loc.details, () => {\n // this.$scope.showPricing();\n // });\n // this.drawerPricing.classes = \"visible-xs\";\n _this.drawerSubmitAndStay = drawerService.addDrawer(_tools.icons.save, $scope.getSubmitAndStayButtonText(), function () {\n _this.submit(true);\n });\n _this.drawerSubmit = drawerService.addDrawer(_tools.icons.quote, $scope.getSubmitButtonText(), function () {\n _this.submit();\n });\n // this.drawerGenerateQrCode = drawerService.addDrawer(icons.add, $scope.getGenerateQrCodeText(), () => {\n // this.qrCodeModal();\n // });\n if ($scope.isEdit) {\n if (_this.$rootScope.isSfdcCpq) {\n _this.drawerSubmit.icon = _tools.icons.save;\n }\n else {\n _this.api.quotes.getById(_this.model.idQuote).then(function (quote) {\n $scope.parentQuote = quote;\n if (_this.$rootScope.isSfdc && !_this.$rootScope.isSfdcCpq) {\n quoteService.quote = quote;\n }\n if ((!quote.idWorkflow && quote.createdBy == _this.$rootScope.user.id) ||\n quote.allowedActions.some(function (a) { return a.type == enums.eWorkflowAction.modifyProducts; })) {\n var builds = quote.allowedActions\n .filter(function (a) { return a.type == enums.eWorkflowAction.buildQuoteProduct; })\n .filter(function (a) { return rootConfig.builds.find(function (b) { return b.idBuildType == a.buildType.id; }) != null; });\n if (builds.length) {\n var drawers_2 = [];\n builds.forEach(function (action) {\n drawers_2.push({\n icon: _tools.icons.gear,\n label: action.buildType.name,\n command: function () {\n _this.submit().then(function () {\n return _this.api.quotes.buildQuoteProduct(quote.id, _this.model.id, action.buildType.id);\n });\n },\n });\n });\n drawerService.addDrawer(_tools.icons.build, 'Build', function () { }, true, drawers_2);\n }\n }\n else {\n drawerService.drawers.remove(_this.drawerSubmit);\n drawerService.drawers.remove(_this.drawerSubmitAndStay);\n $scope.isReadOnly = true;\n drawerService.addDrawer(_tools.icons.cancel, loc.back, function () {\n _this.$state.go('kb.quoteEdit', { id: _this.model.idQuote });\n });\n }\n });\n }\n //after running the configured product, nested configs could have been added to nested\n //sets. We need to set the $nestedSetElement on those configs\n _this.setAllNestedSetElements(rootConfig);\n }\n //this.runContinuousAsyncRule();\n // select the first page after defining the pagechanged handler\n _this.selectNode(rootConfig.pages.find(function (p) { return p.visible == true; }));\n _this.$scope.togglePages(true);\n _this.readyToStart = $q.defer();\n _this.startConfigurator();\n });\n return _this;\n }\n ConfiguratorController_1 = ConfiguratorController;\n ConfiguratorController.prototype.selectNode = function (tab) {\n this.$scope.selected.node = tab;\n };\n ConfiguratorController.prototype.navigateToElement = function (o) {\n var _this = this;\n var animateTo = null;\n var waitFor = 0;\n var waitPromise = new _rules.KPromise(null);\n if (o.visible) {\n if (o instanceof enums.Page) {\n this.selectNode(o);\n }\n else if (o instanceof enums.Configurator) {\n if (o.$parent instanceof enums.NestedSet) {\n var ancestorNestedSets = [o.$parent];\n var p = o.$parent;\n while (p) {\n ancestorNestedSets.push(p);\n if (p.$parentConfigurator.$parent instanceof enums.NestedSet) {\n p = p.$parentConfigurator.$parent;\n }\n else {\n p = null;\n }\n }\n var page = ancestorNestedSets.last().findAncestor(function (kbo) { return kbo instanceof enums.Page; });\n if (page && page.visible) {\n this.selectNode(page);\n animateTo = o;\n for (var i = ancestorNestedSets.length - 1; i >= 0; i--) {\n var nestedSet = ancestorNestedSets[i];\n if (nestedSet.display == enums.eNestedSetDisplay.accordion) {\n waitPromise = waitPromise.then(function () {\n return _this.$timeout(function () {\n if (!o['expanded'])\n waitFor = 350;\n o['expanded'] = true;\n return _this.$timeout(); //we also need to wait for other expanders in the accordion to finish so we return another timeout\n });\n });\n }\n else if (nestedSet.display == enums.eNestedSetDisplay.tabControl) {\n nestedSet['$selectedTab'] = o.name;\n animateTo = nestedSet;\n }\n }\n }\n }\n else {\n this.selectNode(o.pages.find(function (p) { return p.visible; }));\n }\n }\n else {\n var page = o.findAncestor(function (kbo) { return kbo instanceof enums.Page; });\n if (page && page.visible) {\n this.selectNode(page);\n animateTo = o;\n }\n }\n if (animateTo) {\n waitPromise.then(function () {\n _this.$timeout(function () {\n var $uiObject = jQuery('.' + animateTo.$domId + ':visible');\n if ($uiObject.length) {\n _tools.Utils.scrollIntoView({\n elem: $uiObject[0],\n mode: _tools.eScrollMode.middleIfNecessary,\n animate: true,\n });\n }\n }, waitFor);\n });\n }\n }\n };\n ConfiguratorController.prototype.setAllNestedSetElements = function (config) {\n //after running the configured product, nested configs could have been added to nested\n //sets. We need to set the $nestedSetElement on those configs\n for (var _i = 0, _a = config.getAllConfigurators(); _i < _a.length; _i++) {\n var nested = _a[_i];\n this.handleNewConfigInNestedSet(nested, nested.$parent, false);\n }\n };\n ConfiguratorController.prototype.refreshDrawer = function () {\n if (this.$scope.isEmbed) {\n // only show the submit button if the configurator says it should be shown\n if (this.drawerSubmit)\n this.drawerSubmit.visible = this.drawerSubmitAndStay.visible = this.$scope.config.showSubmitButton;\n }\n if (this.$rootScope.isSfdcCpq) {\n if (this.drawerSubmit) {\n var isValid = this.$scope.config.isValid();\n this.drawerSubmit.disabled = !isValid;\n // if (!isValid) {\n // this.drawerService.validationMessage = loc.validation_sfdc_correcterrors;\n // }\n }\n if (this.drawerSubmitAndStay) {\n this.drawerSubmitAndStay.visible = false;\n }\n }\n // if (this.drawerPricing) {\n // this.drawerPricing.visible = (this.$rootScope.user && this.$rootScope.user.canViewPrices && this.$scope.config.showPrice);\n // }\n // let viewerExists = (this.$scope.viewerMode != eViewerMode.none);\n // if (this.drawerViewer) {\n // this.drawerViewer.visible = viewerExists;\n // this.drawerViewer.selected = !this.$scope.showPages;\n // }\n // if (this.drawerOptions) {\n // this.drawerOptions.visible = viewerExists;\n // this.drawerOptions.selected = this.$scope.showPages;\n // }\n };\n ConfiguratorController.prototype.loadSfdcCpqPayload = function () {\n var _this = this;\n if (this.$rootScope.isSfdcCpq) {\n return this.sfdcService.getPayloadFromSfdcCpq().then(function (payload) {\n _this.sfdcCpqPayload = payload;\n _this.$scope.isEdit = _this.sfdcCpqPayload.quoteProductId != null;\n _this.$scope.isNew = !_this.$scope.isEdit;\n _this.$scope.sfdcHasCurrency = false;\n if (payload.data.quote.CurrencyIsoCode) {\n _this.$scope.sfdcCurrency = payload.data.quote.CurrencyIsoCode;\n _this.$scope.sfdcHasCurrency = true;\n }\n });\n }\n else {\n return this.$q.when(null);\n }\n };\n ConfiguratorController.prototype.loadModel = function () {\n var _this = this;\n if (this.$scope.isEdit) {\n var quoteProductId = this.$rootScope.isSfdcCpq ? this.sfdcCpqPayload.quoteProductId : this.$stateParams.id;\n return this.api.quoteProducts.getById(quoteProductId, this.$rootScope.contentTracker).then(function (r) {\n _this.model = r;\n });\n }\n else {\n this.model = {};\n return this.$q.when(null);\n }\n };\n /**\n * depending on the context, we need to figure out the product id for the configurator\n */\n ConfiguratorController.prototype.getProductId = function () {\n if (this.$rootScope.isSfdcCpq) {\n return this.$scope.isEdit ? this.model.idProduct : this.sfdcCpqPayload.productId;\n }\n else {\n return this.$scope.isEdit ? this.model.idProduct : this.$stateParams.id;\n }\n };\n ConfiguratorController.prototype.addTranslationsForEntity = function (entity) {\n var trans = entity.translations.first();\n if (trans) {\n var entry = this.translationDb[entity.id];\n if (!entry)\n entry = this.translationDb[entity.id] = {};\n Object.keys(trans.data.objects).forEach(function (key) {\n entry[key] = trans.data.objects[key];\n });\n }\n };\n /**\n * This controller is used for both full configurators and scene configurators.\n * We load the configurator differently based on the situation\n */\n ConfiguratorController.prototype.getConfigurator = function () {\n var _this = this;\n var configuratorPromise;\n if (this.$scope.isScene) {\n // when we are running a scene configurator, the scene is embedded into the html\n var session = window.serverVm.session;\n var scene = session.scenes.first();\n this.sceneDb[scene.id] = scene;\n this.configSession = { idScene: scene.id, scenes: [scene] };\n this.addTranslationsForEntity(scene);\n this.loadLayout(scene.configurator, session.layout);\n this.helper.loadTables(session.tables);\n var configurator = new enums.Configurator(new enums.KbObjectManager(), scene.configurator);\n configurator.$running = true;\n configuratorPromise = new _rules.KPromise(configurator);\n }\n else {\n // it's a normal configurator\n configuratorPromise = this.authService.authPromise\n .then(function () { return _this.loadSfdcCpqPayload(); })\n .then(function () { return _this.loadModel(); })\n .then(function () {\n var id = _this.getProductId();\n // if we are in test mode, we get the entire product with server rules\n // like pricing rule(so they can be debugged on the client)\n return _this.api.products\n .run(id, _this.$scope.isTest, _this.$rootScope.environment != enums.eEnvironment.dev, //whether to get the configSession pre-compressed\n _this.$rootScope.contentTracker)\n .then(function (session) {\n //special handling for nested parent\n id = session.idProduct;\n _this.configSession = session;\n // load the productDb\n session.products.forEach(function (p) { return (_this.productDb[p.id] = p); });\n // load the scene session db\n session.scenes.forEach(function (s) { return (_this.sceneDb[s.id] = s); });\n // load the translation db\n session.products.forEach(function (p) {\n _this.addTranslationsForEntity(p);\n });\n session.scenes.forEach(function (s) {\n _this.addTranslationsForEntity(s);\n });\n return _this.fillSourcedTables(session).then(function () {\n _this.helper.loadTables(session.tables);\n // fill in the pages / nested configurators db\n _this.$scope.userCanAddToDb = {};\n session.products.forEach(function (product) {\n _this.$scope.userCanAddToDb[product.id] = {};\n if (product.configurator.referencedConfigurators) {\n product.configurator.referencedConfigurators.forEach(function (rc) {\n if (rc.userCanAddTo) {\n rc.userCanAddTo.forEach(function (pageId) {\n var entry = _this.$scope.userCanAddToDb[product.id][pageId] ||\n (_this.$scope.userCanAddToDb[product.id][pageId] = []);\n entry.push({\n id: rc.idProduct,\n name: _this.productDb[rc.idProduct].name,\n });\n });\n }\n });\n }\n });\n _this.$scope.entity = _this.productDb[id];\n var configurator = new enums.Configurator(new enums.KbObjectManager(), _this.productDb[id].configurator);\n configurator.$running = true;\n _this.$scope.showMove = _this.$scope.showMove || configurator.showMoveAnimation;\n if (_this.$scope.embedFields) {\n configurator.setFields(_this.$scope.embedFields);\n }\n if (_this.$scope.isEdit) {\n configurator.runConfiguredProduct(_this.model.configuredProduct, _this.productDb);\n configurator.sku = _this.model.sku;\n configurator.name = _this.model.name;\n configurator.description = _this.model.description;\n configurator.shortDescription = _this.model.shortDescription;\n }\n _this.loadLayout(configurator, session.layout);\n return configurator;\n });\n }, function (err) {\n _this.dialogService.alert({\n type: enums.eAlertType.error,\n msg: 'Product not found',\n persist: true,\n });\n _this.$state.go('kb.products');\n _this.configuratorLoadedDeferred.reject('Product not found');\n return null;\n });\n });\n }\n return configuratorPromise;\n };\n ConfiguratorController.prototype.loadLayout = function (rootConfig, layout) {\n var _this = this;\n this.$scope.layoutConfig = new enums.LayoutConfig(new enums.KbObjectManager(), layout.layoutConfig);\n // load the layout settings into the layout\n if (rootConfig.layoutSettings) {\n rootConfig.layoutSettings.forEach(function (ls) {\n var field = _this.$scope.layoutConfig.$manager.getByIdOrName(ls.id || ls.name, false);\n if (field)\n field.value = ls.value;\n });\n }\n //layout settings from the embed take precedence over those in the configurator properties screen, so we set them after\n if (this.$scope.embedLayoutSettings) {\n for (var lsname in this.$scope.embedLayoutSettings) {\n var field = this.$scope.layoutConfig.$manager.getByIdOrName(lsname, false);\n if (field)\n field.value = this.$scope.embedLayoutSettings[lsname];\n }\n }\n };\n /**\n * starts a configurator by loading any tables it references and running the rules once\n * @param config\n */\n ConfiguratorController.prototype.startConfigurator = function () {\n var _this = this;\n this.readyToStart = this.$q.defer();\n if (this.$scope.deferLoadedRule) {\n _tools.Utils.sendMessageToParent({\n name: 'readyToLoadConfiguredProduct',\n data: {\n requestId: this.requestId,\n },\n });\n }\n else {\n this.readyToStart.resolve();\n }\n return this.readyToStart.promise.then(function () {\n return _this.queueRule(function () {\n return _this.runLayoutRule(_this.rootConfig, _this.getRuleArgs(_this.rootConfig))\n .then(function () {\n //start with layout rule so we don't get FOUC\n return _this.nestedRunBottomsUp(_this.rootConfig, function (c) {\n return _this.runRuleCycleUnit(c, null).then(function () {\n // run the loaded rule\n var args = _this.getLoadedRuleArgs(c);\n var origNumberOfNesteds = c.getNestedConfigurators().length;\n return _this.helper.runRuleTypeAsync(c, enums.eRuleType.resize, args).then(function () {\n return (_this.runLoadedRule(c, args)\n // if the loaded rule changed field values or added nested\n // configs we need to run the rule cycle again\n .then(function () {\n if (c.$fieldsDirty ||\n origNumberOfNesteds != c.getNestedConfigurators().length) {\n return _this.runRuleCycleUnit(c, null);\n }\n }));\n });\n });\n });\n })\n .then(function () {\n _this.loading = false;\n return _this.oncePerCycleRule();\n })\n .then(function () {\n _this.configuratorLoadedDeferred.resolve();\n _tools.Utils.sendMessageToParent({\n name: 'configuratorLoaded',\n data: {\n requestId: _this.requestId,\n },\n });\n });\n });\n });\n };\n ConfiguratorController.prototype.saveToQuote = function () {\n var _this = this;\n //!!!Should only be called by \"submit\". Everything else should call submit() which calls this\n if (this.$rootScope.isSfdcCpq) {\n // if steelbrick, then add the product to a blank quote and submit it\n var quote = this.quoteService.getNewQuote();\n quote.externalId = this.sfdcCpqPayload.data.quote.Id;\n // name the quote the same as the sfdc cpq quote for tracking\n // in version 28.0.1 of steelbrick they took away the record property\n quote.name = this.sfdcCpqPayload.data.quote.record\n ? this.sfdcCpqPayload.data.quote.record.Name\n : this.sfdcCpqPayload.data.quote.Name;\n quote.products = [\n {\n idProduct: this.$scope.entity.id,\n qty: 1,\n configuredProduct: this.rootConfig.getConfiguredProduct(),\n },\n ];\n return this.api.quotes.save(quote, this.$rootScope.contentTracker).then(function (q) {\n // add the quoteproduct id to the payload so it can be saved in sfdc cpq\n _this.sfdcCpqPayload.quoteProductId = q.products[0].id;\n return q.products[0];\n });\n }\n else if (this.$scope.isNew) {\n return this.quoteService\n .addProduct({\n idProduct: this.$scope.entity.id,\n qty: 1,\n configuredProduct: this.rootConfig.getConfiguredProduct(),\n addLocally: true,\n silent: this.$scope.isEmbed,\n currency: this.$scope.getCurrency(),\n })\n .then(function (r) {\n return r;\n });\n }\n else {\n this.model.configuredProduct = this.rootConfig.getConfiguredProduct();\n return this.api.quotes\n .editQuoteProduct(this.model.idQuote, this.model, this.$rootScope.contentTracker)\n .then(function (r) {\n var result = _this.quoteService.getLatestQuoteProduct(r);\n return result;\n });\n }\n };\n ConfiguratorController.prototype.setSubmitButtonDisabled = function (disabled) {\n this.drawerSubmitAndStay.disabled = this.drawerSubmit.disabled = disabled;\n };\n ConfiguratorController.prototype.submit = function (stayOnPage) {\n var _this = this;\n if (stayOnPage === void 0) { stayOnPage = false; }\n this.setSubmitButtonDisabled(true);\n var deferred = this.$q.defer();\n var promise = deferred.promise;\n this.validationPromptDisplayed = false;\n /*\n Process validation before AND after running the submit rule.\n We run it before because in some scenarios people are adding nested configurators in the submit rule,\n and if we're not valid already, then we'd rather not add them.\n We run it after too because perhaps the submit rule changed something that makes it invalid.\n */\n this.shouldSubmit().then(function (should) {\n if (should) {\n _this.runSubmitRule().then(function () {\n _this.shouldSubmit().then(function (should) {\n if (should) {\n _this.saveToQuote().then(function (r) {\n deferred.resolve(r);\n });\n }\n else {\n deferred.reject();\n }\n });\n });\n }\n else {\n deferred.reject();\n }\n });\n return promise\n .then(function (data) {\n _this.telemetryService.trackEvent('Configurator Submit');\n if (_this.$rootScope.isSfdcCpq) {\n _this.sfdcService.saveToSfdcCpq(_this.sfdcCpqPayload, data.priceObject);\n }\n else if (_this.$scope.isNew && !_this.$scope.isEmbed) {\n if (stayOnPage) {\n _this.$state.go('kb.configuredProduct', { id: data.id });\n }\n else {\n _this.quoteService.goToQuote();\n }\n }\n else if (_this.$scope.isEdit) {\n _this.$scope.$broadcast('saveSuccess', data);\n if (!stayOnPage)\n _this.$state.go('kb.quoteEdit', { id: _this.model.idQuote });\n }\n }, function (reason) {\n _this.telemetryService.trackEvent('Configurator Submit Rejected');\n _this.setSubmitButtonDisabled(false);\n return _this.$q.reject(reason);\n })\n .finally(function () {\n if (stayOnPage)\n _this.setSubmitButtonDisabled(false);\n });\n };\n ConfiguratorController.prototype.qrCodeModal = function () {\n var dialogScope = this.$rootScope.$new();\n dialogScope.autoStartAr = false;\n var url = window.location.href;\n if (url.includes('ar=true')) {\n dialogScope.autoStartAr = true;\n }\n dialogScope.updateQrCode = function (newVal) {\n if (newVal !== dialogScope.autoStartAr) {\n dialogScope.autoStartAr = newVal;\n }\n };\n var canvas = document.createElement('canvas');\n browser.toCanvas(canvas, url, { width: 150 }, function (error) {\n if (error)\n console.error(error);\n });\n dialogScope.QrCode = canvas;\n this.dialogService.dialog({\n template: Dirs.view('dialog-create-qr-code', exports.eBundle.app),\n scope: dialogScope,\n buttons: [new enums.InputDialogButton(loc.cancel, _tools.icons.cancel, function (args) { })],\n });\n dialogScope.$watch('autoStartAr', function (newVal) {\n if (newVal === true) {\n if (url.includes('ar=true') === false) {\n url = url + '?ar=true';\n }\n window.history.pushState({}, null, url);\n browser.toCanvas(canvas, url, { width: 150 }, function (error) {\n if (error)\n console.error(error);\n });\n }\n else {\n if (url.includes('ar=true') === true) {\n url = url.replace('ar=true', '');\n if (url.charAt(url.length - 1) === '?') {\n url = url.slice(0, -1);\n }\n }\n window.history.pushState({}, null, url);\n browser.toCanvas(canvas, url, { width: 150 }, function (error) {\n if (error)\n console.error(error);\n });\n }\n var panel = document.getElementById('qrCodeCanvas');\n if (panel instanceof HTMLCanvasElement) {\n var context = panel.getContext('2d');\n context.clearRect(0, 0, canvas.width, canvas.height);\n context.drawImage(canvas, 0, 0);\n //panel.append(canvas);\n }\n //dialogScope.QrCode = canvas;\n }, true);\n setTimeout(function () {\n var panel = document.getElementById('qrCodeCanvas');\n browser.toCanvas(panel, url, { width: 150 }, function (error) {\n if (error)\n console.error(error);\n });\n panel.append(canvas);\n }, 1000);\n };\n ConfiguratorController.prototype.enterArModal = function () {\n var _this = this;\n var dialogScope = this.$rootScope.$new();\n var enterArButton = new enums.InputDialogButton('Enter AR', _tools.icons.change, function (args) {\n if (_this.$scope.activeSceneViewer) {\n _this.$scope.activeSceneViewer.$scope.toggleAr();\n }\n });\n this.dialogService.dialog({\n scope: dialogScope,\n buttons: [enterArButton, new enums.InputDialogButton(loc.cancel, _tools.icons.cancel, function (args) { })],\n });\n };\n ConfiguratorController.prototype.shouldSubmit = function () {\n var deferred = this.$q.defer();\n if (this.rootConfig.isValid()) {\n deferred.resolve(true);\n }\n else {\n //it's not valid\n if (this.rootConfig.allowSaveWithErrors) {\n if (!this.validationPromptDisplayed) {\n this.validationPromptDisplayed = true;\n this.dialogService.dialog({\n content: loc.msg_savetoquoteerrors,\n buttons: [\n new enums.DialogButton(loc.save, _tools.icons.success, function (args) {\n deferred.resolve(true);\n }),\n new enums.DialogButton(loc.keepworking, _tools.icons.cancel, function (args) {\n deferred.resolve(false);\n }),\n ],\n });\n }\n else {\n deferred.resolve(true);\n }\n }\n else {\n this.dialogService.alert({\n msg: loc.msg_fixerrorsbeforesave,\n persist: false,\n type: enums.eAlertType.error,\n });\n deferred.resolve(false);\n }\n }\n return deferred.promise;\n };\n ConfiguratorController.prototype.runConfiguredProduct = function (configurator, configProd) {\n var _this = this;\n return this.queueRule(function () {\n configurator.runConfiguredProduct(configProd, _this.productDb);\n _this.setAllNestedSetElements(configurator);\n return _this.nestedRunBottomsUp(configurator, function (c) { return _this.runRuleCycleUnit(c, null); }).then(function () {\n return _this.oncePerCycleRule();\n });\n });\n };\n ConfiguratorController.prototype.addNestedConfig = function (idNested, parent, addedByUser, name, fields) {\n var _this = this;\n var product = this.productDb[idNested];\n // if a configurator with the given name already exists, then we do nothing\n var nested = parent.configurators.find(function (c) { return c.name.isEqual(name); });\n if (!nested) {\n nested = new enums.Configurator(new enums.KbObjectManager(), product.configurator);\n nested.$running = true;\n if (name)\n nested.name = name;\n parent.$expanded = true;\n parent.configurators.push(nested);\n parent.$manager.addKbObject(nested, parent);\n if (addedByUser)\n nested.addedByUser = this.$rootScope.user.id;\n if (fields) {\n nested.setFields(fields);\n }\n var parentConfig = parent instanceof enums.Configurator ? parent : parent.$parentConfigurator;\n this.handleNewConfigInNestedSet(nested, parent);\n if (this.sceneDb[nested.idScene] && this.sceneDb[nested.idScene].external) {\n nested.nestedPath = nested.idScene;\n }\n else {\n nested.nestedPath = this.getConfiguratorUniqueKey(nested);\n }\n // run the added rule on the nested configurator\n return this.runNestedRuleType(parentConfig, nested, enums.eRuleType.configuratorAdded)\n .then(function () { return _this.runRuleCycleUnit(nested, null, false); }) // don't bubble here\n .then(function () { return nested; });\n }\n else if (fields) {\n nested.setFields(fields); //no need to run\n if (nested.$fieldsDirty) {\n return this.runRuleCycleUnit(nested, null, false).then(function () { return nested; });\n }\n else {\n return new _rules.KPromise(nested);\n }\n }\n else {\n return new _rules.KPromise(nested);\n }\n };\n ConfiguratorController.prototype.getConfiguratorUniqueKey = function (config) {\n var looping = true;\n do {\n var nestedSettings = undefined;\n if (config.$parentConfigurator) {\n nestedSettings = config.$parentConfigurator.referencedConfigurators.find(function (rc) { return rc.name === config.name; });\n }\n if (nestedSettings && nestedSettings.nestScene) {\n config = config.$parentConfigurator;\n }\n else {\n looping = false;\n }\n } while (looping);\n if (config.$parentConfigurator) {\n return config.$parentConfigurator.name + '/' + config.name;\n }\n else {\n return config.name;\n }\n };\n ConfiguratorController.prototype.copyNestedConfig = function (sourceConfig, appendTo, addedByUser, name) {\n var _this = this;\n var product = this.productDb[sourceConfig.idProduct];\n var target = new enums.Configurator(new enums.KbObjectManager(), product.configurator);\n target.$running = true;\n target.runConfiguredProduct(sourceConfig.getConfiguredProduct(), this.productDb);\n target.name = name || product.configurator.name; // get default name\n appendTo.$expanded = true;\n appendTo.configurators.push(target);\n appendTo.$manager.addKbObject(target, appendTo);\n if (addedByUser)\n target.addedByUser = this.$rootScope.user.id;\n this.handleNewConfigInNestedSet(target, appendTo);\n // run the added rule on the nested configurator\n return this.runNestedRuleType(sourceConfig.$parentConfigurator, target, enums.eRuleType.configuratorCopied)\n .then(function () { return _this.nestedRunBottomsUp(target, function (c) { return _this.runRuleCycleUnit(c, null); }); })\n .then(function () { return _this.oncePerCycleRule(); })\n .then(function () { return target; });\n };\n ConfiguratorController.prototype.handleNewConfigInNestedSet = function (nested, parent, navigateTo) {\n var _this = this;\n if (navigateTo === void 0) { navigateTo = true; }\n //we need to save a handle to the element chosen to represent the nested set so we can access it in our angular view\n if (parent && parent instanceof enums.NestedSet) {\n //get the referenced configurator\n var refConfig = parent.$parentConfigurator.referencedConfigurators.find(function (rc) { return rc.idProduct == nested.idProduct; });\n nested.$nestedSetElement = nested.$manager.get(refConfig.element);\n if (parent.visible && parent.autoNavigateToElement && navigateTo) {\n this.$timeout(function () {\n _this.navigateToElement(nested);\n });\n }\n }\n };\n ConfiguratorController.prototype.removeNestedConfig = function (nested) {\n var _this = this;\n return new _rules.KPromise(nested).then(function () {\n if (nested) {\n // might be a page or configurator passed in. If it's a page,\n // it's the page's parent configurator that needs to be deleted\n if (nested instanceof enums.Page || nested instanceof enums.NestedSet)\n nested = nested.$parentConfigurator;\n // we need a new selection if we are deleting the page we're on\n if (_this.$scope.selected.page) {\n if (_this.$scope.selected.page.findAncestor(function (a) { return a == nested; })) {\n if (nested.$parent instanceof enums.Page) {\n _this.selectNode(nested.$parent);\n }\n else {\n _this.selectNode(nested.$parent.pages.find(function (p) { return p.visible; }));\n }\n }\n }\n nested.$parent.$manager.removeKbObject(nested);\n nested.$parent.configurators.remove(nested);\n var parentConfig = nested.$parent instanceof enums.Configurator\n ? nested.$parent\n : nested.$parent.$parentConfigurator;\n // run the removed rule on the nested configurator\n return _this.runNestedRuleType(parentConfig, nested, enums.eRuleType.configuratorRemoved);\n }\n });\n };\n ConfiguratorController.prototype.setNumberOfNestedConfigs = function (productId, parent, num) {\n var _this = this;\n var product = this.productDb[productId];\n var configs = parent.configurators.filter(function (c) { return c.idProduct == productId; });\n var promises = [];\n var configsChanged = false;\n if (configs.length < num) {\n // need to add\n for (var i = configs.length; i < num; i++) {\n configsChanged = true;\n promises.push(this.addNestedConfig(productId, parent, false, null));\n }\n }\n else if (configs.length > num) {\n // need to remove\n for (var i = configs.length - 1; i >= num; i--) {\n configsChanged = true;\n promises.push(this.removeNestedConfig(configs[i]));\n }\n }\n var prom = this.$q.all(promises);\n if (configsChanged) {\n var parentConfig_1 = parent instanceof enums.Configurator ? parent : parent.$parentConfigurator;\n prom = prom.then(function () { return _this.runRuleCycleUnit(parentConfig_1, null); });\n }\n return prom;\n };\n ConfiguratorController.prototype.getChildrenForNode = function (tabNode) {\n var _this = this;\n var nodes = [];\n tabNode.node.pages.forEach(function (p) {\n if (p.visible && !_this.$scope.selected.isSingleNode(p.$parentConfigurator)) {\n var child = { id: p.id, level: tabNode.level + 1, node: p };\n nodes.push(child);\n nodes.pushArray(_this.getChildrenForNode(child));\n }\n });\n tabNode.node.configurators.forEach(function (c) {\n var child = { id: c.id, level: tabNode.level + 1, node: c };\n nodes.push(child);\n nodes.pushArray(_this.getChildrenForNode(child));\n });\n return nodes;\n };\n ConfiguratorController.prototype.calculateNodes = function () {\n var rootNode = { id: this.rootConfig.id, level: -1, node: this.rootConfig };\n this.$scope.nodes = [];\n this.$scope.nodes.pushArray(this.getChildrenForNode(rootNode));\n this.$scope.nextNode = this.getNextNode(this.$scope.selected.page, false);\n this.$scope.backNode = this.getBackNode(this.$scope.selected.node);\n };\n ConfiguratorController.prototype.getNextNode = function (node, skipChildren) {\n var next;\n if (node) {\n var parent_2 = node.$parent;\n if (!skipChildren) {\n // first find if there is a nested page\n next = node.pages.find(function (p) { return p.visible; });\n // then check nested configurators\n if (!next)\n next = node.configurators.find(function (c) { return c.pages.some(function (p) { return p.visible; }); });\n }\n // get next page or configurator with the same parent\n if (!next && parent_2) {\n if (node instanceof enums.Page) {\n next = parent_2.pages.next(node, function (p) { return p.visible; });\n }\n if (!next)\n next = parent_2.configurators.next(node, function (c) { return c.pages.some(function (p) { return p.visible; }); });\n }\n if (!next && parent_2)\n next = this.getNextNode(parent_2, true);\n }\n return next;\n };\n ConfiguratorController.prototype.getBackNode = function (node) {\n var prev;\n if (node) {\n var parent_3 = node.$parent;\n // find the previous item\n if (node instanceof enums.Configurator) {\n prev = parent_3.configurators.previous(node, function (c) { return c.pages.some(function (p) { return p.visible; }); });\n }\n if (!prev)\n prev = parent_3.pages.previous(node, function (p) { return p.visible; });\n if (prev) {\n var n = prev;\n while (n) {\n // find the last nested child\n n = prev.configurators.filter(function (c) { return c.pages.some(function (p) { return p.visible; }); }).last();\n if (!n)\n n = prev.pages.filter(function (p) { return p.visible; }).last();\n if (n)\n prev = n;\n }\n }\n else {\n // if there was no siblings, then go to the parent\n if (!prev && parent_3 != this.rootConfig)\n prev = parent_3;\n if (prev instanceof enums.Configurator)\n prev = this.getBackNode(prev);\n }\n }\n return prev;\n };\n ConfiguratorController.prototype.queueRule = function (ruleAction) {\n if (this.activeRule) {\n this.activeRule = this.activeRule.then(function () {\n return ruleAction();\n });\n }\n else {\n this.activeRule = ruleAction();\n }\n return this.activeRule;\n };\n ConfiguratorController.prototype.oncePerCycleRule = function () {\n var _this = this;\n return new _rules.KPromise((function () {\n _this.runPricing();\n _this.calculateNodes();\n _this.getCurrentConfigForViewerAndSetViewerMode(); //need to set viewerMode before layout rule so the layout rule can show/hide the viewer accordingly\n })())\n .then(function () { return _this.runLayoutRule(_this.$scope.config, _this.getRuleArgs(_this.$scope.config)); })\n .then(function () { return !_this.loading && _this.refreshViewer(); })\n .then(function () {\n _this.$scope.actionsVisible = _this.$scope.config.actions.some(function (a) { return a.visible; });\n _this.$timeout(function () {\n //this.resizeActionBar();\n _this.refreshDrawer();\n });\n });\n };\n ConfiguratorController.prototype.runLoadedRule = function (config, args) {\n if (!this.$scope.isScene && !config.$ranLoadedRule) {\n //scene loaded rule is handled by the viewer\n config.$ranLoadedRule = true;\n return this.helper.runRuleTypeAsync(config, enums.eRuleType.loaded, args);\n }\n return new _rules.KPromise({ parameters: args, hasError: false });\n };\n /**\n * manages bubbling the value rule running up or down. We do this isolated,\n * so we don't end up over-running other rules (like validation, pricing, scene).\n * Returns a boolean indicating whether the configurator fields were dirty immediately\n * after running the value rule (indicating whether something before or during the value\n * rule actually modified a field)\n * @param config\n * @param field\n */\n ConfiguratorController.prototype.runRuleCycleUnit = function (config, field, bubble) {\n var _this = this;\n if (bubble === void 0) { bubble = true; }\n if (this.runningRules[config.name] >= ConfiguratorController_1.cycleLimit) {\n console.log(\"Rule cycle recursion limit hit for configurator '\".concat(config.name, \"'. Opting out of running\"));\n return this.$q.when(false);\n }\n if (!this.runningRules[config.name])\n this.runningRules[config.name] = 1;\n else\n this.runningRules[config.name]++;\n var nestedRulesRan = false;\n var ruleArgs = this.getRuleArgs(config, field);\n var origNumberOfNesteds = config.getNestedConfigurators().length;\n var configWasDirty = false;\n var runRules = this.helper\n .runSelects(config)\n // value rules\n .then(function () { return _this.helper.runRuleTypeAsync(config, enums.eRuleType.value, ruleArgs); })\n .then(function () {\n configWasDirty = config.$fieldsDirty;\n // reset $fieldsDirty of this configurator so it doesn't affect a\n // parent's decision on whether to run the child's rules\n config.$fieldsDirty = false;\n })\n .then(function () {\n // run rule cycle on dirty nesteds\n var promises = [];\n config.getNestedConfigurators().forEach(function (nested) {\n /* if the nested configurator was changed by the parent rules OR\n if the nested is setup to be always a child, and this parent actually had a change\n then we need to run the nested's value rule */\n if (nested.$fieldsDirty || (nested.alwaysChild && nested.alwaysChildOf && configWasDirty)) {\n nestedRulesRan = true;\n // don't bubble the nested rules here. We'll take care of it at the parent level next\n promises.push(_this.runRuleCycleUnit(nested, null, false));\n }\n });\n return _this.$q.all(promises);\n })\n .then(function (dirtyArr) {\n // after running nested config rule cycles, if this parent is referencing them,\n // it now needs to be updated we do this here instead of using the bubbling below\n // so that the parent only re - runs it's rules once, instead of once for each nested\n return nestedRulesRan &&\n ((!_this.loading && dirtyArr && dirtyArr.some(function (b) { return b == true; })) || //make sure that one of the nesteds is actually dirty or it's pointless to re-run this config's value rule\n (_this.loading && origNumberOfNesteds < config.getNestedConfigurators().length)) && // if we are loading, then only bubble if a new nested configurator was added by the value rule\n config.bubbleRules &&\n _this.helper.runRuleTypeAsync(config, enums.eRuleType.value, ruleArgs);\n })\n .then(function () {\n return _this.runValidationRule(config, ruleArgs);\n })\n .then(function () { return _this.helper.runRuleTypeAsync(config, enums.eRuleType.visibility, ruleArgs); })\n .then(function () {\n // as opposed to the bubbling above, this bubbling is more for the user having changed\n // a field value in the nested configurator directly and us sensing that the parent now\n // needs to update. (only if we are done loading, since loading bubbles through all\n // configurators anyways)\n return !_this.loading &&\n bubble &&\n config.$parentConfigurator &&\n config.$parentConfigurator.bubbleRules &&\n _this.runRuleCycleUnit(config.$parentConfigurator, null);\n })\n .then(function () {\n delete _this.runningRules[config.name];\n });\n return runRules.then(function () { return configWasDirty; });\n };\n ConfiguratorController.prototype.queueEventRuleType = function (config, ruleType, args) {\n var rc = config.ruleContainers.find(function (rc) {\n return rc.ruleType.isEqual(ruleType);\n });\n return this.queueEventRule(config, rc, args);\n };\n /** wraps the given delegate to run a rule, and follows it with a rule cycle if the event rule changed something that warrants it */\n ConfiguratorController.prototype.queueEventRule = function (config, ruleContainer, args) {\n var _this = this;\n return this.queueRule(function () {\n //if there is no rule for the rule type, then cut it off here so we don't run oncePerCycleRule unnecessarily\n if (ruleContainer && ruleContainer.js) {\n var origNumberOfNesteds_1 = config.getNestedConfigurators().length;\n return _this.helper.runRuleContainerAsync(ruleContainer, args).then(function () {\n var nesteds = config.getNestedConfigurators();\n if (config.$fieldsDirty ||\n (_this.$scope.layoutConfig && _this.$scope.layoutConfig.$layoutSettingsDirty) ||\n origNumberOfNesteds_1 != nesteds.length ||\n nesteds.some(function (n) { return n.$fieldsDirty; })) {\n return _this.runRuleCycleUnit(config, null).then(function () { return _this.oncePerCycleRule(); });\n }\n else if (ruleContainer.ruleType.isEqual(enums.eRuleType.tabChanged) &&\n ruleContainer.references.length) {\n _this.refreshViewer(true);\n }\n else {\n _this.$scope.$digest(); //because of the way event queueing works, we need to $digest here\n }\n });\n }\n else {\n var result = {\n hasError: false,\n parameters: args,\n };\n return new _rules.KPromise(result);\n }\n });\n };\n /**\n * Runs the given function on the configurator given and all of it's child configurators in the direction given\n * @param fn\n */\n ConfiguratorController.prototype.nestedRunTopDown = function (config, fn) {\n var _this = this;\n var nesteds = config.getNestedConfigurators();\n return fn(config).then(function () { return _this.$q.all(nesteds.map(function (n) { return _this.nestedRunTopDown(n, fn); })); });\n };\n ConfiguratorController.prototype.nestedRunBottomsUp = function (config, fn) {\n var _this = this;\n var nesteds = config.getNestedConfigurators();\n var continueRun = function () { return _this.$q.all(nesteds.map(function (n) { return _this.nestedRunBottomsUp(n, fn); })); };\n if (this.loading && nesteds.some(function (n) { return n.alwaysChild; })) {\n return this.nestedRunTopDown(config, fn)\n .then(continueRun)\n .then(function () { return fn(config); });\n }\n else {\n return continueRun().then(function () { return fn(config); });\n }\n };\n ConfiguratorController.prototype.runNestedRuleType = function (config, nested, ruleType, args) {\n if (!args)\n args = this.getRuleArgs(config);\n args.nested = nested;\n var refConfig = config.referencedConfigurators.find(function (rc) { return rc.idProduct == nested.idProduct; });\n var ruleContainer = refConfig.ruleContainers.find(function (rc) { return rc.ruleType.isEqual(ruleType); });\n if (ruleContainer) {\n return this.helper.runRuleContainerAsync(ruleContainer, args);\n }\n else {\n return this.$q.when(null);\n }\n };\n ConfiguratorController.prototype.runValidationRule = function (config, ruleArgs) {\n config.preValidate(); // call internal validation for fields\n return this.helper.runRuleTypeAsync(config, enums.eRuleType.validation, ruleArgs).then(function () {\n config.isValid(); //force recalculation of $valid property\n });\n };\n ConfiguratorController.prototype.runLayoutRule = function (config, ruleArgs) {\n var _this = this;\n return this.helper.runRuleTypeAsync(this.$scope.config, enums.eRuleType.layout, ruleArgs).then(function () {\n _this.$scope.layoutConfig.$layoutSettingsDirty = false;\n if (!_this.$scope.layoutLoaded) {\n _this.$scope.layoutLoaded = true;\n if (_this.$scope.config.hasRule(enums.eRuleType.layout)) {\n /**\n * Process UI changes when first running so there is no FOUC.\n * Note that we only call this if there is actually a layout rule, because\n * otherwise the runRuleTypeAsync above actually resolves synchronously because it's\n * a KbPromise, then we get an error on the $digest call that there is already one in\n * progress\n */\n _this.$scope.$digest();\n }\n }\n return _this.$scope.resizeScene();\n });\n };\n ConfiguratorController.prototype.runSubmitRule = function () {\n var _this = this;\n console.log('runSubmitRule');\n this.runAsyncRule = false;\n this.rootConfig.parameters = this.getParameters();\n return this.queueRule(function () {\n return _this.nestedRunBottomsUp(_this.rootConfig, function (c) {\n var origNumberOfNesteds = c.getNestedConfigurators().length;\n var ruleArgs = _this.getLoadedRuleArgs(c);\n //set all fields to be \"touched\" and re-run validation to satisfy configurator.validationTiming setting\n c.getFields().forEach(function (f) { return (f.hasBeenTouched = true); });\n return _this.runValidationRule(c, ruleArgs).then(function () {\n return _this.helper.runRuleTypeAsync(c, enums.eRuleType.submit, ruleArgs).then(function () {\n var nesteds = c.getNestedConfigurators();\n //if the submit rule changed any fields or added nested configurators, run another rule cycle\n if (c.$fieldsDirty ||\n origNumberOfNesteds != nesteds.length ||\n nesteds.some(function (n) { return n.$fieldsDirty; })) {\n return _this.runRuleCycleUnit(c, null);\n }\n });\n });\n }).then(function () {\n _this.telemetryService.trackEvent('Configurator Submit Rule Run');\n });\n });\n };\n ConfiguratorController.prototype.showErrors = function () {\n return (this.$scope.isScene ||\n this.$scope.isTest ||\n this.$rootScope.environment == enums.eEnvironment.dev ||\n this.$rootScope.environment == enums.eEnvironment.test);\n };\n ConfiguratorController.prototype.getRuleArgs = function (config, changedField) {\n var ruleArgs = new ConfiguratorRuleArgs(this);\n ruleArgs.user = this.$rootScope.user;\n ruleArgs.environment = this.$rootScope.environment;\n ruleArgs.baseUrl = this.$rootScope.context.baseUrl;\n ruleArgs.configurator = config;\n ruleArgs.layoutConfig = this.$scope.layoutConfig;\n ruleArgs.kom = config.$manager;\n ruleArgs.parentKom = config.$parentConfigurator ? config.$parentConfigurator.$manager : null;\n ruleArgs.changedField = changedField;\n ruleArgs.logs = new _rules.ClientLogger();\n ruleArgs.clientLanguage = this.$rootScope.clientLanguage;\n ruleArgs.viewerMode = this.$scope.viewerMode;\n ruleArgs.isCrm = this.$rootScope.isSfdc || this.$rootScope.isSfdcCpq;\n ruleArgs.parameters = this.getParameters();\n return ruleArgs;\n };\n ConfiguratorController.prototype.getLoadedRuleArgs = function (config) {\n var args = jQuery.extend(this.getRuleArgs(config), {\n isEdit: this.$scope.isEdit || (this.$scope.isKinetic && this.$scope.deferLoadedRule),\n quoteProduct: this.$scope.isEdit || this.$scope.deferLoadedRule ? this.model : null,\n });\n return args;\n };\n ConfiguratorController.prototype.createSceneViewer = function (scene) {\n var _this = this;\n var sceneViewer;\n var viewerScope = this.$scope.$new();\n var company = this.$rootScope.company;\n var env = this.$rootScope.environment;\n var vArgs = {\n //$rootScope: this.$rootScope,\n //$http: this.$http,\n environment: this.$rootScope.environment,\n baseUrl: this.$rootScope.context.baseUrl,\n assetRoot: this.$rootScope.context.publicStorageUrl,\n clusterEnv: this.$rootScope.context.clusterEnv,\n cacheBuster: this.$rootScope.context.cacheBuster,\n clientLanguage: this.$rootScope.clientLanguage,\n isMobile: this.$rootScope.windowWidth < _tools.Utils.MOBILE_WIDTH,\n isRender: false,\n renderPass: null,\n $q: this.$q,\n $timeout: this.$timeout,\n $injector: this.$injector,\n ruleService: this.ruleService,\n //uploadService: this.uploadService,\n dialogService: this.dialogService,\n highlightColor: this.themeService.getActiveTheme().accent,\n //$compile: this.$compile,\n $scope: viewerScope,\n handleRuleError: function (ruleName, result) { return _this.helper.handleRuleError(ruleName, result); },\n tableArraysDb: this.helper.tableArraysDb,\n //helper: this.helper,\n elemSelector: '.kb-viewer',\n //isEmbed: true,\n bare: false,\n requestId: null,\n // scene: scene,\n sceneDb: this.sceneDb,\n configSession: this.configSession,\n messageCallback: null,\n configuratorLoadedPromise: this.configuratorLoadedDeferred.promise,\n arLoading: this.$scope.arLoading,\n navigateToElement: function (o) {\n _this.navigateToElement(o);\n },\n compileTemplate: function (hotspotDiv, scope) {\n return _this.$compile(hotspotDiv)(scope)[0];\n },\n lastDeploy: env == enums.eEnvironment.dev\n ? 0\n : env == enums.eEnvironment.test\n ? company.lastTestDeployment\n : company.lastProdDeployment,\n };\n if (scene.external) {\n var cArgs = vArgs;\n cArgs.sceneService = this.$injector.get(Token.ClaraSceneService.key);\n cArgs.playerUrl = this.$rootScope.context.claraV2LibraryUrl;\n cArgs.ocLazyLoad = this.ocLazyLoad;\n sceneViewer = new ClaraViewer(cArgs);\n }\n else {\n sceneViewer = new Kb3dViewer(vArgs);\n }\n return sceneViewer.init().then(function () {\n viewerScope.$on('$destroy', function () {\n sceneViewer.dispose();\n });\n return sceneViewer;\n });\n };\n ConfiguratorController.prototype.runSceneAction = function (config, actionName) {\n var _this = this;\n if (this.lastViewerPromise) {\n return this.lastViewerPromise.then(function () {\n return _this.$scope.activeSceneViewer && _this.$scope.activeSceneViewer.runAction(actionName);\n });\n }\n else {\n return this.refreshViewer().then(function () {\n return _this.$scope.activeSceneViewer && _this.$scope.activeSceneViewer.runAction(actionName);\n });\n }\n };\n ConfiguratorController.prototype.getCurrentConfigForViewerAndSetViewerMode = function () {\n var currentConfig = this.rootConfig;\n if (this.$scope.selected.page)\n currentConfig = this.$scope.selected.page.$parentConfigurator;\n // find the closest config that should show a 3d viewer\n while (currentConfig) {\n if (currentConfig.viewerMode == enums.eViewerMode.media || currentConfig.viewerMode == enums.eViewerMode.none) {\n break;\n }\n else if (currentConfig.viewerMode == enums.eViewerMode.scene && currentConfig.idScene) {\n if (!currentConfig.$parent)\n break;\n // it's nested: we only show it if it's not set to merge scenes with it's parent\n var refConfig = currentConfig.$parentConfigurator.referencedConfigurators.find(function (rc) { return rc.idProduct == currentConfig.idProduct; });\n if (!refConfig.nestScene)\n break;\n }\n currentConfig = currentConfig.$parentConfigurator;\n }\n if (!currentConfig) {\n this.$scope.viewerMode = enums.eViewerMode.none;\n }\n else {\n this.$scope.viewerMode = currentConfig.viewerMode;\n }\n return currentConfig;\n };\n ConfiguratorController.prototype.refreshViewer = function (skipRules) {\n var _this = this;\n if (skipRules === void 0) { skipRules = false; }\n if (!this.lastViewerPromise)\n this.lastViewerPromise = new _rules.KPromise(null);\n this.lastViewerPromise = this.lastViewerPromise.then(function () {\n var viewerDeferred = _this.$q.defer();\n var origSceneViewer = _this.$scope.activeSceneViewer;\n var origConfig = origSceneViewer ? origSceneViewer.uiConfig : null;\n var currentConfig = _this.getCurrentConfigForViewerAndSetViewerMode();\n if (currentConfig) {\n if (_this.sceneDb[currentConfig.idScene] && _this.sceneDb[currentConfig.idScene].external) {\n currentConfig.nestedPath = currentConfig.idScene;\n }\n else {\n currentConfig.nestedPath = _this.getConfiguratorUniqueKey(currentConfig);\n }\n if (currentConfig.viewerMode == enums.eViewerMode.media) {\n _this.$scope.viewerMediaPath = currentConfig.viewerMediaPath;\n viewerDeferred.resolve();\n }\n else if (currentConfig.viewerMode == enums.eViewerMode.scene) {\n var clear = _this.rootConfig.clearMemoryWhenSwitchingScenes &&\n _this.$scope.activeSceneViewer &&\n _this.$scope.activeSceneViewer.scene.id != currentConfig.idScene;\n /**\n * for kb3d if we are clearing memory we just dispose of the old viewer and make a new one\n */\n if (clear && !_this.sceneDb[currentConfig.idScene].external) {\n delete _this.sceneViewerDb[currentConfig.nestedPath];\n origSceneViewer.dispose();\n _this.$scope.activeSceneViewer = null;\n clear = false;\n }\n if (clear) {\n _this.$timeout(function () {\n _this.sceneViewerDb[currentConfig.nestedPath] = _this.$scope.activeSceneViewer;\n _this.$scope.activeSceneViewer\n .loadScene({\n scene: _this.sceneDb[currentConfig.idScene],\n clearMemory: true,\n config: currentConfig,\n isStandalone: _this.$scope.isScene,\n isRenderContext: false,\n })\n .then(function () { return viewerDeferred.resolve(); });\n }, 0);\n }\n else {\n _this.$scope.activeSceneViewer = _this.sceneViewerDb[currentConfig.nestedPath];\n if (_this.$scope.activeSceneViewer) {\n // execute scene on next frame so configurator appears responsive\n _this.$timeout(function () {\n // if we are switching configurators, but keeping the same sceneViewer,\n // then we need to clear the clickDb\n if (_this.$scope.activeSceneViewer.uiConfig != currentConfig) {\n _this.$scope.activeSceneViewer.clearHandlers();\n }\n // set the uiConfig of the viewer\n if (_this.$scope.activeSceneViewer.sceneConfig.idProduct == currentConfig.idProduct) {\n currentConfig.$sceneConfigurator = _this.$scope.activeSceneViewer.sceneConfig;\n _this.$scope.activeSceneViewer.sceneConfig.$uiConfigurator = currentConfig;\n _this.$scope.activeSceneViewer.uiConfig = currentConfig;\n }\n //only skip rules if we are told to and we haven't switched scene viewers\n if (skipRules && _this.$scope.activeSceneViewer.uiConfig == origConfig) {\n viewerDeferred.resolve();\n }\n else {\n _this.$scope.activeSceneViewer\n .runRules(true)\n //.then(result => this.helper.handleRuleError(eRuleType.scene, result))\n .then(function () { return viewerDeferred.resolve(); });\n }\n }, 0);\n }\n else {\n // init the sceneViewer which also runs the rules\n //if there is no viewer in the layout, then we skip\n if (!_this.isViewerInLayout()) {\n viewerDeferred.resolve();\n }\n else {\n _this.waitForViewerReady().then(function () {\n var scene = _this.sceneDb[currentConfig.idScene];\n _this.createSceneViewer(scene).then(function (sceneViewer) {\n _this.$scope.activeSceneViewer = sceneViewer;\n _this.sceneViewerDb[currentConfig.nestedPath] =\n _this.$scope.activeSceneViewer;\n _this.$scope.activeSceneViewer\n .loadScene({\n scene: scene,\n clearMemory: _this.rootConfig.clearMemoryWhenSwitchingScenes,\n config: currentConfig,\n isStandalone: _this.$scope.isScene,\n isRenderContext: false,\n })\n .then(function () { return viewerDeferred.resolve(); });\n });\n }, function (err) {\n viewerDeferred.reject(err);\n });\n }\n }\n }\n }\n else {\n viewerDeferred.resolve();\n }\n }\n else {\n viewerDeferred.resolve();\n }\n // set other viewers to hide\n Object.keys(_this.sceneViewerDb).forEach(function (key) {\n if (_this.$scope.viewerMode != enums.eViewerMode.scene ||\n _this.$scope.activeSceneViewer !== _this.sceneViewerDb[key]) {\n _this.sceneViewerDb[key].hide();\n }\n else {\n _this.sceneViewerDb[key].show();\n }\n });\n return viewerDeferred.promise;\n });\n // console.log(this.configuratorMap);\n // console.log(this.nestedSceneMap);\n return this.lastViewerPromise;\n };\n ConfiguratorController.prototype.isViewerInLayout = function () {\n return this.$scope.config.getChildrenOfType(enums.CToken.Viewer).some(function (v) { return v.visible; });\n };\n ConfiguratorController.prototype.waitForViewerReady = function () {\n if (!this.isViewerInLayout()) {\n return new _rules.KPromise(null);\n }\n else {\n var elemDefer_1 = Q.defer();\n var waitedFor_1 = 0;\n var wait_1 = 30;\n var check_1 = function () {\n var parentElem = document.querySelector('.kb-viewer');\n if (parentElem && parentElem.getBoundingClientRect().height > 0) {\n if (waitedFor_1)\n console.log(\"waited \".concat(waitedFor_1, \"ms for viewer ready\"));\n elemDefer_1.resolve();\n }\n else {\n setTimeout(function () {\n waitedFor_1 += wait_1;\n check_1();\n }, wait_1);\n }\n };\n check_1();\n return elemDefer_1.promise;\n }\n };\n ConfiguratorController.prototype.hasPricing = function () {\n return (this.rootConfig.hasPricingRule ||\n this.hasNestedPricing() ||\n (this.$scope.isTest && this.rootConfig.ruleContainers.some(function (rc) { return rc.ruleType == enums.eRuleType.pricing; })));\n };\n ConfiguratorController.prototype.runPricing = function () {\n var _this = this;\n var promise = new _rules.KPromise(null);\n if (this.hasPricing()) {\n var configuredProduct = this.rootConfig.getConfiguredProduct();\n promise = this.lastPricingPromise = this.$http\n .post('/api/products/' + this.$scope.entity.id + '/pricing', configuredProduct, {\n tracker: this.$scope.pricingTracker,\n })\n .then(function (response) {\n _this.rootConfig.priceObject = _this.$scope.priceObject = response.data;\n }, function (error) {\n _this.helper.handleRuleError('Pricing Rule', {\n hasError: true,\n error: new Error(error.data.error),\n parameters: _this.getRuleArgs(_this.rootConfig),\n });\n });\n }\n return promise;\n };\n ConfiguratorController.prototype.addLevelsToPricing = function (item, level) {\n var _this = this;\n if (level === void 0) { level = -1; }\n var o = item;\n if (o) {\n o.$level = level;\n item.items && item.items.forEach(function (i) { return _this.addLevelsToPricing(i, level + 1); });\n }\n };\n ConfiguratorController.prototype.hasNestedPricing = function () {\n var _this = this;\n return this.rootConfig\n .getNestedConfigurators()\n .some(function (nested) {\n return nested.hasPricingRule &&\n _this.rootConfig.referencedConfigurators.find(function (rc) { return rc.idProduct == nested.idProduct; }).nestPriceObject;\n });\n };\n ConfiguratorController.prototype.setScene = function (configurator, idScene) {\n if (configurator.idScene != idScene) {\n configurator.idScene = idScene;\n configurator.$nestedSceneId = null;\n configurator.$sceneConfigurator = null;\n return this.refreshViewer();\n }\n return new _rules.KPromise(null);\n };\n ConfiguratorController.prototype.trackConfigPageView = function (page) {\n if (page) {\n var path = page.name;\n var parent_4 = page.$parentConfigurator;\n while (parent_4.$parentConfigurator) {\n path = \"\".concat(parent_4.name, \"/\").concat(path);\n parent_4 = parent_4.$parentConfigurator;\n }\n this.telemetryService.trackEvent('Configurator Page View', { pageName: path });\n }\n };\n ConfiguratorController.prototype.getParameters = function () {\n var _a, _b;\n var parameters = _tools.Utils.extend(this.$location.search(), this.$scope.embedParameters);\n // combine query string parameters with sfdc parameters\n if (this.$rootScope.context.sfdcCanvasRequest) {\n parameters = _tools.Utils.extend(this.$rootScope.context.sfdcCanvasRequest.context.environment.parameters, parameters);\n if (this.$rootScope.isSfdcCpq) {\n parameters.sfdcQuote = this.sfdcCpqPayload.fullQuote;\n parameters.sfdcConfiguredProductId = this.sfdcCpqPayload.data.product.configuredProductId;\n parameters.sfdcQuoteLine = (_b = (_a = this.sfdcCpqPayload) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.product;\n }\n }\n return parameters;\n };\n ConfiguratorController.prototype.runContinuousAsyncRule = function (id, timeSeconds) {\n var _this = this;\n if (!this.scheduledRules)\n this.scheduledRules = [];\n if (this.scheduledRules.find(function (a) { return a.id == id; })) {\n this.cancelScheduledRule(id);\n }\n var interval = this.$interval(function () {\n if (_this.$rootScope && _this.runAsyncRule) {\n _this.$rootScope.showSpinner = false;\n return _this.helper.runActionByIdAsync(_this.rootConfig, id).then(function (result) {\n _this.$rootScope.showSpinner = true;\n _this.$rootScope.$apply();\n // TODO: Will need to run this conditionally on whether a rule cycle\n // actually needs to be run after an interval is run.\n //this.runRuleCycleUnit(this.$scope.config, null);\n });\n }\n }, timeSeconds * 1000);\n this.scheduledRules.push({\n id: id,\n promise: interval\n });\n };\n ConfiguratorController.prototype.cancelScheduledRule = function (id) {\n if (this.scheduledRules && this.scheduledRules.length > 0) {\n var runningRule = this.scheduledRules.find(function (a) { return a.id == id; });\n if (runningRule) {\n this.$interval.cancel(runningRule.promise);\n this.scheduledRules.remove(runningRule);\n }\n }\n return;\n };\n ConfiguratorController.prototype.runTimeoutRule = function (func, timeSeconds) {\n var _this = this;\n this.$timeout(function () {\n //this.$rootScope.showSpinner = false;\n if (_this.$rootScope && _this.runAsyncRule) {\n _this.$rootScope.showSpinner = false;\n var res = func();\n if (res instanceof Promise) {\n return res.then(function () {\n _this.$rootScope.showSpinner = true;\n });\n }\n else {\n return res;\n }\n // return this.helper.runActionByIdAsync(this.rootConfig, id).then(() => {\n // this.$rootScope.showSpinner = true;\n // this.$rootScope.$apply();\n // });\n }\n }, timeSeconds * 1000);\n };\n ConfiguratorController.prototype.fillSourcedTables = function (session) {\n var tablePromise = new _rules.KPromise(null);\n if (session.sourcedTableIds && session.sourcedTableIds.length) {\n return this.api.tables.getBatch({ ids: session.sourcedTableIds }).then(function (sourcedTables) {\n if (sourcedTables && sourcedTables.length) {\n session.tables.pushArray(sourcedTables);\n }\n });\n }\n else {\n return new _rules.KPromise(null);\n }\n };\n var ConfiguratorController_1;\n ConfiguratorController.cycleLimit = 2;\n ConfiguratorController = ConfiguratorController_1 = __decorate([\n NgView({\n token: Token.ConfiguratorView,\n dependencies: [\n Token.$Scope,\n Token.$Q,\n Token.$Location,\n Token.$State,\n Token.$StateParams,\n Token.$Http,\n Token.$RootScope,\n Token.$Window,\n Token.$Compile,\n Token.$Injector,\n Token.DialogService,\n Token.$Timeout,\n Token.$Interval,\n Token.$Filter,\n Token.DrawerService,\n Token.RuleService,\n Token.UploadService,\n Token.AuthService,\n Token.QuoteService,\n Token.PromiseTracker,\n Token.ApiService,\n Token.ThemeService,\n Token.SfdcService,\n Token.KbService,\n Token.TelemetryService,\n Token.InteractionService,\n Token.$OcLazyLoad,\n ],\n })\n ], ConfiguratorController);\n return ConfiguratorController;\n }(BaseController));\n\n var ProductCompareController = /** @class */ (function (_super) {\n __extends(ProductCompareController, _super);\n function ProductCompareController($scope, $state, $rootScope, api, drawerService, quoteService, model) {\n var _this = _super.call(this) || this;\n drawerService.setHelpUrl(\"Products\");\n drawerService.pageTitle = loc.productcomparison;\n drawerService.pageType = loc.product;\n drawerService.pageIcon = _tools.icons.cast;\n $scope.model = model;\n $scope.addToQuote = function (product) {\n quoteService.addProduct({ idProduct: product.id, qty: product.minQty, addLocally: true });\n };\n $scope.removeProduct = function (id) {\n $rootScope.comparedProducts.removeWhere(function (p) { return p == id; });\n if ($rootScope.comparedProducts.length > 0) {\n $state.go(\"kb.productCompare\", { ids: $rootScope.comparedProducts });\n }\n else {\n $state.go(\"kb.products\");\n }\n };\n return _this;\n }\n ProductCompareController = __decorate([\n NgView({\n token: Token.ProductCompareView,\n dependencies: [\n Token.$Scope,\n Token.$State,\n Token.$RootScope,\n Token.ApiService,\n Token.DrawerService,\n Token.QuoteService,\n Token.Model\n ],\n resolves: [\n {\n name: \"model\",\n dependencies: [\n Token.ApiService,\n Token.AuthService,\n Token.$StateParams,\n Token.$RootScope,\n ],\n fn: function (api, authService, $stateParams, $rootScope) {\n return authService.authPromise.then(function () {\n return api.products.getBatch({ ids: $stateParams.ids }, $rootScope.contentTracker);\n }\n // api.products.search({ \n // query: `id:(${$stateParams.ids.join(\" OR \")})`\n // }, $rootScope.contentTracker)\n );\n }\n }\n ]\n })\n ], ProductCompareController);\n return ProductCompareController;\n }(BaseController));\n\n var ProductController = /** @class */ (function (_super) {\n __extends(ProductController, _super);\n function ProductController($scope, $state, $rootScope, api, drawerService, quoteService, dialogService, model) {\n var _this = _super.call(this) || this;\n drawerService.setHelpUrl(\"Products\");\n drawerService.pageTitle = $scope.model.name;\n drawerService.pageType = loc.product;\n drawerService.pageIcon = _tools.icons.standardProducts;\n $scope.model = model;\n $scope.qty = $scope.model.minQty;\n if (model.images && model.images.length > 0) {\n $scope.selectedMedia = model.images[0].imagePath;\n }\n $scope.selectMedia = function (path) {\n $scope.selectedMedia = path;\n };\n $scope.addToQuote = function () {\n quoteService.addProduct({ idProduct: $scope.model.id, qty: $scope.qty, addLocally: true });\n };\n $scope.getVolumeDiscountText = function (volumeDiscount) {\n var result = volumeDiscount.qty.toString();\n var nextTier = null;\n var orderedVolumeDiscounts = $scope.model.volumeDiscounts.sort(function (a, b) { return a.qty - b.qty; });\n for (var i = 0; i < orderedVolumeDiscounts.length; i++) {\n if (orderedVolumeDiscounts[i].qty == volumeDiscount.qty) {\n nextTier = orderedVolumeDiscounts[i + 1];\n break;\n }\n }\n if (nextTier) {\n result += \" \" + loc.to + \" \" + (nextTier.qty - 1).toString() + \" \" + loc.units;\n }\n else {\n result += \" \" + loc.units + \" \" + loc.andabove + \": \";\n }\n return result;\n };\n api.products.searchByCategory({\n query: (model.relatedProductsQuery ? model.relatedProductsQuery : model.name) + \" -id:\" + model.id,\n take: 5,\n skip: 0\n }).then(function (r) { return $scope.relatedProducts = r; });\n // add drawers\n if (model.isConfigured) {\n var drConfigure = drawerService.addDrawer(_tools.icons.gear, \"Configure\", function () { return $state.go(\"kb.configurator\", { id: model.id }); });\n }\n else {\n var drAdd = drawerService.addDrawer(_tools.icons.add, loc.addtoquote, $scope.addToQuote);\n }\n if (!$rootScope.comparedProducts.contains($scope.model.id)) {\n drawerService.addDrawer(_tools.icons.cast, loc.compare, function () {\n if ($rootScope.comparedProducts.length >= 4) {\n dialogService.alert({\n msg: loc.msg_productcomparisonlimit,\n type: enums.eAlertType.info\n });\n }\n else {\n $rootScope.comparedProducts.push($scope.model.id);\n $state.go(\"kb.products\");\n }\n });\n }\n return _this;\n }\n ProductController = __decorate([\n NgView({\n token: Token.ProductView,\n dependencies: [\n Token.$Scope,\n Token.$State,\n Token.$RootScope,\n Token.ApiService,\n Token.DrawerService,\n Token.QuoteService,\n Token.DialogService,\n Token.Model\n ],\n resolves: [\n {\n name: \"model\",\n dependencies: [\n Token.ApiService,\n Token.AuthService,\n Token.$StateParams,\n Token.$RootScope,\n ],\n fn: function (api, authService, $stateParams, $rootScope) {\n return authService.authPromise.then(function () {\n return api.products.getById($stateParams.id, $rootScope.contentTracker);\n });\n }\n }\n ]\n })\n ], ProductController);\n return ProductController;\n }(BaseController));\n\n var ProductsController = /** @class */ (function (_super) {\n __extends(ProductsController, _super);\n function ProductsController($scope, agg, kbService, quoteService, categories) {\n var _this = _super.call(this, $scope, agg, true) || this;\n _this.$scope = $scope;\n _this.agg = agg;\n _this.kbService = kbService;\n _this.quoteService = quoteService;\n _this.categories = categories;\n _this.flatCategories = [];\n agg.drawerService.setHelpUrl(\"Products\");\n agg.drawerService.pageType = loc.products;\n agg.drawerService.pageIcon = _tools.icons.products;\n $scope.categories = categories;\n _this.flatCategories = categories.flatten(function (c) { return c.items; });\n $scope.attributeDb = {};\n for (var _i = 0, _a = _this.flatCategories; _i < _a.length; _i++) {\n var c = _a[_i];\n if (c.attributes) {\n for (var _b = 0, _c = c.attributes; _b < _c.length; _b++) {\n var a = _c[_b];\n $scope.attributeDb[a.id] = a;\n }\n }\n }\n $scope.savedSearchEnabled = false;\n $scope.customResults = true;\n if (agg.$state.params.imagemode) {\n $scope.imageMode = (agg.$state.params.imagemode == \"true\");\n }\n else {\n $scope.imageMode = agg.$rootScope.context.companySettings.displayProductsInImageModeByDefault;\n }\n $scope.setToImageMode = function () {\n $scope.imageMode = true;\n // pageSize = 35;\n };\n $scope.setToListMode = function () {\n $scope.imageMode = false;\n // pageSize = 11;\n };\n $scope.getChildCategories = function (cat) {\n return _this.getChildCategories(cat);\n };\n $scope.translateSuggestion = function (item) {\n var name = item.name;\n if (agg.$rootScope.companySettings.defaultLanguage != agg.$rootScope.clientLanguage && item.translations) {\n var translation = item.translations.find(function (t) { return t.languageIso == agg.$rootScope.clientLanguage; });\n if (translation) {\n name = translation.name || item.name;\n }\n }\n return name;\n };\n // when the category selection is changed, fire a search\n $scope.$watch(\"binding.selectedCategory\", function (newVal, oldVal) {\n if (newVal !== oldVal) {\n _this.$scope.binding.search.selectedCategoryId = newVal.id;\n _this.refreshAttributeFilters();\n $scope.reload();\n }\n });\n var addProductPromise = new _rules.KPromise(null);\n $scope.addToQuote = function (product, qty) {\n if (product.isConfigured) {\n agg.$state.go(\"kb.configurator\", { id: product.id });\n }\n else {\n kbService.fly(\"#product_\" + product.id.toString() + \"_image\", \"#product-fly-target\", function () {\n addProductPromise = addProductPromise.then(function () {\n return quoteService.addProduct({ idProduct: product.id, qty: qty, addLocally: true });\n });\n });\n }\n };\n _this.init();\n _this.loadSelectedCategory();\n _this.refreshAttributeFilters();\n return _this;\n }\n ProductsController.prototype.preInit = function () {\n };\n ProductsController.prototype.client = function (api) {\n return api.products;\n };\n ProductsController.prototype.getQueryStringParams = function () {\n return { imagemode: this.$scope.imageMode };\n };\n ProductsController.prototype.searchCall = function (args, tracker) {\n args.categoryIds = [];\n if (this.$scope.binding.selectedCategory.id >= 0) {\n args.categoryIds = this.getChildCategories(this.$scope.binding.selectedCategory);\n }\n return this.client(this.agg.api).searchByCategory(args, tracker);\n };\n ProductsController.prototype.loadedFromQueryString = function (search) {\n this.loadSelectedCategory();\n };\n ProductsController.prototype.massageResults = function (items) {\n //add a property to the product for the UI to control the qty getting added to the quote\n items.forEach(function (p) { return p.$addQty = p.minQty; });\n };\n ProductsController.prototype.loadSelectedCategory = function () {\n var _this = this;\n if (this.$scope.binding.search.selectedCategoryId == null)\n this.$scope.binding.search.selectedCategoryId = -1;\n this.$scope.binding.selectedCategory = this.getCategory(this.$scope.categories, this.$scope.binding.search.selectedCategoryId);\n this.agg.$timeout(function () {\n _this.expandToSelectedCategory();\n }, 0);\n };\n ProductsController.prototype.newSearch = function () {\n var _this = this;\n return {\n selectedCategoryId: -1,\n modelType: enums.meta.Product.$name,\n sortField: \"score\",\n descending: true,\n filters: (function () {\n var filters = [];\n filters.push({\n type: enums.eFilterType.sort,\n label: loc.sortby,\n control: enums.eFilterControl.select,\n sourceType: enums.eFilterSource.productSorts,\n valueField: \"value\",\n labelField: \"label\",\n values: [enums.eProductSortBy.relevance],\n sticky: true\n });\n filters.pushArray(_this.getFiltersFromMeta(enums.meta.Product.$name, true));\n return filters;\n })()\n };\n };\n ProductsController.prototype.getCategory = function (cats, id) {\n if (cats) {\n for (var _i = 0, cats_1 = cats; _i < cats_1.length; _i++) {\n var cat = cats_1[_i];\n if (cat.id == id) {\n return cat;\n }\n var match = this.getCategory(cat.items, id);\n if (match) {\n return match;\n }\n }\n }\n return null;\n };\n /** gets an array of the selected category id and all of it's children id's used for filtering the search results*/\n ProductsController.prototype.getChildCategories = function (cat) {\n var _this = this;\n var ids = [];\n ids.push(cat.id);\n cat.items.forEach(function (child) {\n ids = ids.concat(_this.getChildCategories(child));\n });\n return ids;\n };\n ProductsController.prototype.expandToSelectedCategory = function () {\n var addParentRef = function (cats, parent) {\n cats.forEach(function (cat) {\n cat.$parent = parent;\n if (cat.items)\n addParentRef(cat.items, cat);\n });\n };\n addParentRef(this.$scope.categories, null);\n var selectedAncestors = [];\n var p = this.$scope.binding.selectedCategory;\n while (p) {\n selectedAncestors.push(p);\n p = p.$parent;\n }\n selectedAncestors.forEach(function (a) { return a.expanded = true; });\n };\n ProductsController.prototype.refreshAttributeFilters = function () {\n var availableAtts = this.getSelectedCategoryAttributes();\n //remove available attribute filters\n this.$scope.availableFilters.removeWhere(function (f) { return f.type == enums.eFilterType.attribute; });\n //remove any existing filters that are referencing attributes no longer applicable\n this.$scope.binding.search.filters.removeWhere(function (f) { return f.type == enums.eFilterType.attribute && !availableAtts.some(function (a) { return a.name == f.fieldName; }); });\n var attFilters = this.$scope.binding.search.filters.filter(function (f) { return f.type == enums.eFilterType.attribute; });\n var _loop_1 = function (a) {\n if (!attFilters.find(function (f) { return f.attributeId == a.id; })) { //only add the attribute filter it if it's not already a filter\n var f = {\n type: enums.eFilterType.attribute,\n fieldName: a.name,\n label: a.name,\n fieldType: a.type,\n sourceType: enums.eFilterSource.attributes,\n values: [null],\n attributeId: a.id\n };\n if (a.default) {\n this_1.$scope.binding.search.filters.push(f);\n }\n else {\n this_1.$scope.availableFilters.push(f);\n }\n }\n };\n var this_1 = this;\n for (var _i = 0, availableAtts_1 = availableAtts; _i < availableAtts_1.length; _i++) {\n var a = availableAtts_1[_i];\n _loop_1(a);\n }\n this.fillFilters(); //fill the filters again so it fills the attribute filters\n };\n ProductsController.prototype.getSelectedCategoryAttributes = function () {\n var parentCats = {};\n var selectedCat = this.$scope.binding.selectedCategory;\n this.flatCategories.filter(function (c) { return selectedCat.lft >= c.lft && selectedCat.rgt <= c.rgt; }).forEach(function (c) { return parentCats[c.id] = c; });\n return Object.values(parentCats).selectMany(function (c) { return c.attributes; });\n };\n ProductsController = __decorate([\n NgView({\n token: Token.ProductsView,\n dependencies: [\n Token.$Scope,\n Token.SearchService,\n Token.KbService,\n Token.QuoteService,\n Token.Categories\n ],\n resolves: [\n {\n name: \"categories\",\n dependencies: [\n Token.$RootScope,\n Token.AuthService,\n Token.ApiService\n ],\n fn: function ($rootScope, authService, api) {\n return authService.authPromise.then(function () {\n return api.categories.tree({ onlyActiveCategories: true }, $rootScope.contentTracker).then(function (r) {\n r.unshift({ name: loc.all, id: -1 });\n return r;\n });\n });\n }\n }\n ]\n })\n ], ProductsController);\n return ProductsController;\n }(SearchController));\n\n var ConfiguredProductsController = /** @class */ (function (_super) {\n __extends(ConfiguredProductsController, _super);\n function ConfiguredProductsController($scope, agg, quoteService) {\n var _this = _super.call(this, $scope, agg) || this;\n _this.$scope = $scope;\n agg.drawerService.setHelpUrl(\"Quotes\");\n agg.drawerService.pageType = loc.configuredproducts;\n agg.drawerService.pageIcon = _tools.icons.quote;\n $scope.binding.search.modelType = enums.meta.QuoteProduct.$name;\n $scope.savedSearchEnabled = true;\n _this.refreshSavedSearches();\n $scope.modelTypes = [\n { type: enums.meta.Quote.$name, label: \"Quotes\", state: \"kb.quotes\" },\n { type: enums.meta.QuoteProduct.$name, label: \"Configured Products\", state: \"kb.configuredProducts\" }\n ];\n _this.massageFilters($scope.availableFilters);\n $scope.availableFilters.pushArray([\n _this.getWhereFieldFilter()\n ]);\n var fieldsDb = {};\n $scope.$watch(\"binding.search.filters[0].values[0]\", function (newVal, oldVal) {\n if (newVal) {\n agg.api.configurators.searchFields(newVal).then(function (r) {\n fieldsDb = {};\n r.forEach(function (field) { return fieldsDb[field.name] = field; });\n $scope.filterSource[enums.eFilterSource.fields] = r;\n });\n }\n });\n // $scope.getFilterControlForField = (fieldName) => {\n // var field = fieldsDb[fieldName];\n // var fieldType = field ? field.type : eFieldType.text;\n // if (fieldType == eFieldType.number)\n // return eFilterControl.numberRange;\n // else if (fieldType == eFieldType.boolean)\n // return eFilterControl.checkbox;\n // else\n // return eFilterControl.text;\n // };\n $scope.fieldChange = function (filter) {\n var field = fieldsDb[filter.fieldName];\n var fieldType = field ? field.type : enums.eFieldType.text;\n filter.fieldType = fieldType;\n if (fieldType == enums.eFieldType.number) {\n filter.control = enums.eFilterControl.numberRange;\n }\n else if (fieldType == enums.eFieldType.boolean) {\n filter.control = enums.eFilterControl.checkbox;\n }\n else {\n filter.control = enums.eFilterControl.text;\n }\n };\n $scope.showCopyToActiveQuoteBtn = function (qp) {\n /** only show this 'copy to active quote' button if we are not in the active quote, and the active quote allows modifying products */\n return (quoteService.quote\n && quoteService.canModifyProductsOfQuote(quoteService.quote)\n && !agg.$rootScope.isSfdc //this should never happen in CRM integration\n );\n };\n $scope.showCopyToNewQuoteBtn = function (qp) {\n return !agg.$rootScope.isSfdc; //creating a new quote in this way would break the CRM integration\n };\n $scope.copyProductToActiveQuote = function (qp) {\n return quoteService.copyProductToActiveQuote(qp.id).then(function (r) {\n quoteService.goToQuote();\n });\n };\n $scope.copyProductToNewQuote = function (qp) {\n return quoteService.copyProductToNewQuote(qp.id).then(function (r) {\n quoteService.goToQuote();\n });\n };\n agg.drawerService.addDrawer(_tools.icons.clone, loc.clone, function () { return _this.clone(); });\n agg.drawerService.addDrawer(_tools.icons.deleter, loc.deleter, function () { return _this.deleteItems(); });\n return _this;\n }\n ConfiguredProductsController.prototype.client = function (api) {\n if (this.agg.$rootScope.company.useDatabaseSearch) {\n return api.quoteProducts;\n }\n else {\n return api.quotes;\n }\n };\n ConfiguredProductsController.prototype.newSearch = function () {\n var _this = this;\n return {\n modelType: enums.meta.QuoteProduct.$name,\n sortField: \"modifiedDate\",\n descending: true,\n filters: (function () {\n var filters = [];\n filters.push({\n type: enums.eFilterType.property,\n property: \"idProduct\",\n label: \"Product Type\",\n control: enums.eFilterControl.select,\n sourceType: enums.eFilterSource.configurators,\n valueField: \"id\",\n labelField: \"name\",\n values: [null],\n sticky: true\n }, _this.getWhereFieldFilter());\n filters.pushArray(_this.getFiltersFromMeta(enums.meta.QuoteProduct.$name, true));\n _this.massageFilters(filters);\n return filters;\n })()\n };\n };\n ConfiguredProductsController.prototype.massageFilters = function (filters) {\n if (!this.agg.$rootScope.company.useDatabaseSearch) {\n // configured products is a tricky screen since we're searching for quotes, \n // but really try to show stuff about products\n // so we need to massage the filters to add the nested property syntax\n filters.forEach(function (f) {\n if (f.property && !f.property.startsWith(\"products.\")) {\n f.property = \"products.\" + f.property;\n }\n });\n }\n };\n ConfiguredProductsController.prototype.postProcessFilters = function (filters) {\n //don't send the product type filter if they haven't selected one\n filters.removeWhere(function (f) { return f.property == \"idProduct\" && !f.values.first(); });\n };\n /**\n * the properties of the queried objec that should be returned.\n */\n ConfiguredProductsController.prototype.fields = function () {\n if (this.agg.$rootScope.company.useDatabaseSearch) {\n return [\n enums.meta.QuoteProduct.id.name,\n enums.meta.QuoteProduct.name.name,\n enums.meta.QuoteProduct.imagePath.name,\n enums.meta.QuoteProduct.shortDescription.name,\n enums.meta.QuoteProduct.price.name,\n enums.meta.QuoteProduct.sku.name,\n enums.meta.QuoteProduct.idQuote.name,\n enums.meta.QuoteProduct.quote.name,\n enums.meta.QuoteProduct.currency.name,\n enums.meta.QuoteProduct.modifiedDate.name\n ];\n }\n else {\n return [\n enums.meta.Quote.id.name,\n enums.meta.Quote.name.name,\n enums.meta.Quote.description.name,\n enums.meta.Quote.customer.name,\n enums.meta.Quote.idCustomer.name,\n enums.meta.Quote.contact.name,\n enums.meta.Quote.idContact.name,\n enums.meta.Quote.totalPrice.name,\n enums.meta.Quote.state.name,\n enums.meta.Quote.createdDate.name,\n enums.meta.Quote.modifiedDate.name,\n enums.meta.Quote.ownedBy.name,\n enums.meta.Quote.owner.name,\n enums.meta.Quote.currency.name\n ];\n }\n };\n ConfiguredProductsController.prototype.nestedFields = function () {\n if (this.agg.$rootScope.company.useDatabaseSearch) {\n return [];\n }\n else {\n return [\n enums.meta.QuoteProduct.id.name,\n enums.meta.QuoteProduct.name.name,\n enums.meta.QuoteProduct.imagePath.name,\n enums.meta.QuoteProduct.shortDescription.name,\n enums.meta.QuoteProduct.price.name,\n enums.meta.QuoteProduct.sku.name\n ];\n }\n };\n ConfiguredProductsController.prototype.getNestedPath = function () {\n if (this.agg.$rootScope.company.useDatabaseSearch) {\n return null;\n }\n else {\n return \"products\";\n }\n };\n // public getRawFilter() {\n // return { term: { isConfigured: true } };\n // }\n ConfiguredProductsController.prototype.getWhereFieldFilter = function () {\n return {\n type: enums.eFilterType.fieldValue,\n label: \"Where Field\",\n fieldName: null,\n control: enums.eFilterControl.none,\n sourceType: enums.eFilterSource.fields,\n values: [null]\n };\n };\n ConfiguredProductsController.prototype.getExtraFilters = function () {\n if (this.agg.$rootScope.company.useDatabaseSearch) {\n return [\n {\n property: enums.meta.QuoteProduct.isConfigured.name,\n values: [true]\n }\n ];\n }\n else {\n return [];\n }\n };\n ConfiguredProductsController = __decorate([\n NgView({\n token: Token.ConfiguredProductsView,\n inherit: [Token.SearchView],\n dependencies: [\n Token.QuoteService,\n ]\n })\n ], ConfiguredProductsController);\n return ConfiguredProductsController;\n }(SearchController));\n\n var QuoteHeaderRuleArgs = /** @class */ (function () {\n function QuoteHeaderRuleArgs(ctrl) {\n this.ctrl = ctrl;\n this.isMobile = ctrl.$rootScope.windowWidth < _tools.Utils.MOBILE_WIDTH;\n this.windowWidth = ctrl.$rootScope.windowWidth;\n this.windowHeight = ctrl.$rootScope.windowHeight;\n }\n QuoteHeaderRuleArgs.prototype.getTables = function (args) {\n var _this = this;\n return new _rules.KPromise(args.ids.map(function (tid) { return _this.ctrl.helper.tableArraysDb[tid]; }));\n };\n QuoteHeaderRuleArgs.prototype.sendMessage = function (msg) {\n // send message to embed consumer\n _tools.Utils.sendMessageToParent({ name: msg.name, data: msg.data });\n this.ctrl.sfdcService.sendMessage(msg);\n };\n QuoteHeaderRuleArgs.prototype.convertCurrency = function (obj) {\n return this.ctrl.kbService.fxConvertAsync(obj.amount, obj.currencyCode);\n };\n QuoteHeaderRuleArgs.prototype.callSafeFunction = function (obj) {\n return this.ctrl.api.safeFunctions.run(obj.safeFunctionId, obj.parameters, this.ctrl.$rootScope.contentTracker);\n };\n QuoteHeaderRuleArgs.prototype.generateNumber = function (args) {\n return this.ctrl.api.generators.next(args.generatorId, this.ctrl.$rootScope.contentTracker);\n };\n QuoteHeaderRuleArgs.prototype.selectPage = function (page) {\n this.ctrl.$scope.selectedPageId = page.id;\n };\n QuoteHeaderRuleArgs.prototype.navigateToElement = function (elem) {\n var page = elem.findAncestor(function (kbo) { return kbo instanceof enums.Page; });\n if (page && page.visible) {\n this.ctrl.$scope.selectedPageId = page.id;\n }\n };\n QuoteHeaderRuleArgs.prototype.nextPage = function () {\n var selectedPage = this.configurator.$manager.get(this.ctrl.$scope.selectedPageId, false);\n if (selectedPage) {\n var index = this.configurator.pages.indexOf(selectedPage);\n if (index >= 0 && index < this.configurator.pages.length - 1) {\n this.ctrl.$scope.selectedPageId = this.configurator.pages[index + 1].id;\n }\n }\n };\n QuoteHeaderRuleArgs.prototype.backPage = function () {\n var selectedPage = this.configurator.$manager.get(this.ctrl.$scope.selectedPageId, false);\n if (selectedPage) {\n var index = this.configurator.pages.indexOf(selectedPage);\n if (index >= 0 && index > 0) {\n this.ctrl.$scope.selectedPageId = this.configurator.pages[index - 1].id;\n }\n }\n };\n QuoteHeaderRuleArgs.prototype.upload = function () { return this.ctrl.$q.when(null); };\n QuoteHeaderRuleArgs.prototype.runSceneAction = function (name) { return this.ctrl.$q.when(null); };\n QuoteHeaderRuleArgs.prototype.callSceneFunction = function (args) { return this.ctrl.$q.when(null); };\n QuoteHeaderRuleArgs.prototype.setScene = function (args) { return this.ctrl.$q.when(null); };\n QuoteHeaderRuleArgs.prototype.runNamingRule = function () { return this.ctrl.$q.when(null); };\n QuoteHeaderRuleArgs.prototype.addNestedConfigurator = function (idProduct, idParent, name) { return this.ctrl.$q.when(null); };\n QuoteHeaderRuleArgs.prototype.copyNestedConfigurator = function (nested, idParent, name) { return this.ctrl.$q.when(null); };\n QuoteHeaderRuleArgs.prototype.setNumberOfNestedConfigurators = function (idProduct, idParent, n) { return this.ctrl.$q.when(null); };\n QuoteHeaderRuleArgs.prototype.removeNestedConfigurator = function (nested) { return this.ctrl.$q.when(null); };\n QuoteHeaderRuleArgs.prototype.showPriceDetails = function () { };\n QuoteHeaderRuleArgs.prototype.alert = function (args) { this.ctrl.dialogService.alert(args); };\n QuoteHeaderRuleArgs.prototype.getOptionFilterSource = function (idOptionFilter, fromConfigurator) {\n fromConfigurator = fromConfigurator || this.configurator;\n var f = fromConfigurator.$manager.get(idOptionFilter);\n return new _rules.KPromise(f ? f.$source : []);\n };\n QuoteHeaderRuleArgs.prototype.setLayoutSetting = function (id, value) { };\n QuoteHeaderRuleArgs.prototype.getLayoutSetting = function (id) { };\n QuoteHeaderRuleArgs.prototype.runConfiguredProduct = function (cp) { };\n return QuoteHeaderRuleArgs;\n }());\n var QuoteController = /** @class */ (function (_super) {\n __extends(QuoteController, _super);\n function QuoteController($scope, crudService, model, header, quoteService, sfdcService, ruleService, $filter, $timeout, $interval, $location, uploadService, kbService, storageService) {\n var _this = _super.call(this, $scope, crudService, model) || this;\n _this.$scope = $scope;\n _this.header = header;\n _this.quoteService = quoteService;\n _this.sfdcService = sfdcService;\n _this.ruleService = ruleService;\n _this.$filter = $filter;\n _this.$timeout = $timeout;\n _this.$interval = $interval;\n _this.$location = $location;\n _this.uploadService = uploadService;\n _this.kbService = kbService;\n _this.storageService = storageService;\n _this.translationDb = {};\n _this.bypassUnsavedConfirmation = !!model.idWorkflow;\n _this.drawerService.setHelpUrl(\"Quotes\");\n _this.drawerService.pageTitle = _this.$scope.model ? _this.$scope.model.name : loc.newquote;\n _this.drawerService.pageType = loc.quote_title;\n _this.drawerService.pageIcon = _tools.icons.quote;\n $scope.v = {};\n $scope.customers = [];\n $scope.contacts = [];\n $scope.currencies = [];\n $scope.validationMessages = [];\n $scope.binding = {};\n $scope.selectedTab = \"tab_basic\";\n $scope.productsInView = [];\n $scope.productBuildTypes = {};\n /*$rootScope.$on(events.loginSuccessful, () =>\n {\n this.subscribe().finally(() =>\n {\n if (this.submitQuotePending) {\n this.submitQuotePending = false;\n this.dialogService.confirm(\"Would you like to continue submitting your quote?\", () =>\n {\n this.submit();\n });\n }\n });\n });*/\n var thisCtrl = _this;\n $scope.upload = function (file, field) {\n var uploadOptions = {\n convertPdfToImage: field.convertUploadPdfToImage\n };\n return thisCtrl.uploadService.uploadQuoteFile(file, uploadOptions).then(function (uuid) {\n var uploadValue = field.value;\n uploadValue.path = uuid;\n // clear the asset id in case there was an old file there that was just \n // replaced to make sure the new file is uploaded to the scene\n uploadValue.assetId = null;\n });\n };\n var viewType = _this.$state.current.data.viewType;\n if ($scope.model) {\n _this.deleteMsg = loc.msg_deleterecord.format(loc.quote_title, $scope.model.name);\n }\n _this.onRelationshipEdited(\"Files\", function (m) {\n _this.setUpdatedModelInternal(m, false);\n });\n if (viewType == enums.eViewType.new) {\n var idCategory = _this.$location.search().idcategory;\n model = $scope.model = quoteService.getNewQuote();\n if (_this.sfdcService.record() && _this.sfdcService.record().Name) {\n $scope.model.name = _this.sfdcService.record().Name;\n }\n }\n if (_this.$rootScope.isSfdc && !_this.$rootScope.isSfdcCpq) {\n quoteService.quote = _this.$scope.model;\n }\n $scope.updateName = function () {\n if ($scope.model.state) {\n if (_this.validate() || _this.$rootScope.context.companySettings.allowInvalidQuotesInWorkflow) {\n $scope.executeAction(enums.eWorkflowAction.modifyName);\n }\n else {\n _this.promptUserToFixErrors();\n _this.revertToClean();\n }\n }\n };\n $scope.updateCurrency = function () {\n if ($scope.model.state) {\n if (_this.validate() || _this.$rootScope.context.companySettings.allowInvalidQuotesInWorkflow) {\n $scope.executeAction(enums.eWorkflowAction.modifyCurrency);\n }\n else if ($scope.model.state) {\n _this.promptUserToFixErrors();\n _this.revertToClean();\n }\n }\n };\n $scope.updateCustomer = function () {\n // update the customer name for display (when the kbAtom is not active)\n var customer = $scope.customers.find(function (c) { return c.id == $scope.model.idCustomer; });\n $scope.model.customer = customer ? customer.name : null;\n var contact = $scope.contacts.find(function (c) { return c.id == $scope.model.idContact; });\n $scope.model.contact = contact ? contact.name : null;\n if ($scope.model.state) {\n if (_this.validate() || _this.$rootScope.context.companySettings.allowInvalidQuotesInWorkflow) {\n $scope.executeAction(enums.eWorkflowAction.modifyCustomer);\n }\n else if ($scope.model.state) {\n _this.promptUserToFixErrors();\n _this.revertToClean();\n }\n }\n };\n $scope.updateDiscount = function () {\n if ($scope.model.state) {\n if (_this.validate() || _this.$rootScope.context.companySettings.allowInvalidQuotesInWorkflow) {\n $scope.executeAction(enums.eWorkflowAction.modifyDiscount);\n }\n else if ($scope.model.state) {\n _this.promptUserToFixErrors();\n _this.revertToClean();\n }\n }\n };\n $scope.updateShipping = function () {\n if ($scope.model.state) {\n if (_this.validate() || _this.$rootScope.context.companySettings.allowInvalidQuotesInWorkflow) {\n $scope.executeAction(enums.eWorkflowAction.modifyShipping);\n }\n else if ($scope.model.state) {\n _this.promptUserToFixErrors();\n _this.revertToClean();\n }\n }\n };\n $scope.updateProduct = function (quoteProduct) {\n if (_this.validate() || _this.$rootScope.context.companySettings.allowInvalidQuotesInWorkflow) {\n if ($scope.model.idWorkflow || quoteProduct.requiresUpdate) {\n // we are in a workflow so we need to run the action OR we need to update\n // the product to re - run it's pricing rule (if it uses the qtyInQuote variable)\n return $scope.executeAction(enums.eWorkflowAction.modifyProducts, quoteProduct);\n }\n }\n else if ($scope.model.state) {\n _this.promptUserToFixErrors();\n _this.revertToClean();\n }\n };\n $scope.updateProductDescription = function (quoteProduct) {\n if (_this.validate()) {\n if ($scope.model.idWorkflow || quoteProduct.requiresUpdate) {\n // we are in a workflow so we need to run the action OR we need to update the product\n // to re - run it's pricing rule (if it uses the qtyInQuote variable)\n return $scope.executeAction(enums.eWorkflowAction.modifyQuoteProductDescription, quoteProduct);\n }\n }\n };\n if (!$scope.model.discountPercentage)\n $scope.model.discountPercentage = 0;\n $scope.getAvailableProductBuildTypes = function (product) {\n var result = [];\n if (product.isConfigured && _this.$scope.productBuildTypes[product.idProduct]) {\n result = $scope.availableProductBuildTypes.filter(function (b) { return _this.$scope.productBuildTypes[product.idProduct].contains(b.id); });\n }\n return result;\n };\n $scope.buildProduct = function (product, idBuildType) {\n _this.api.quotes.buildQuoteProduct(_this.$scope.model.id, product.id, idBuildType).then(function (q) {\n _this.handleActionResponse(q, enums.eWorkflowAction.buildQuoteProduct);\n _this.dialogService.alert({\n type: enums.eAlertType.success,\n persist: false,\n msg: loc.quoteproductbuilding\n });\n });\n };\n $scope.commentListApi = {\n refresh: function () {\n }\n };\n $scope.downloadQuoteProductFile = function (file) {\n _this.$window.open(\"/api/quotes/productfile/download/\" + file.id, \"_blank\");\n };\n $scope.addProduct = function () {\n _this.validate();\n if (!_this.$scope.model.name)\n return;\n // save the current quote\n quoteService.quote = $scope.model;\n $scope.executeAction(enums.eWorkflowAction.save).then(function () {\n _this.bypassUnsavedConfirmation = true;\n _this.$state.go(\"kb.products\");\n });\n };\n var expandedProducts = {};\n $scope.isExpanded = function (product) {\n return expandedProducts[product.id];\n };\n $scope.toggleExpansion = function (product, expand) {\n if (expand == null) {\n expandedProducts[product.id] = !expandedProducts[product.id];\n }\n else {\n expandedProducts[product.id] = expand;\n }\n };\n $scope.downloadAttachment = function (item) {\n if (item.source == enums.eFileSource.media) {\n window.open(storageService.getMediaUrl(item.filePath));\n }\n else {\n window.open(\"api/quotes/file/download/\" + item.id, \"_blank\");\n }\n };\n $scope.hasFileGenerating = function (product) {\n return product.files && product.files.some(function (f) { return f.status == enums.eFileStatus.generating; });\n };\n $scope.deleteProduct = function (product) {\n _this.dialogService.dialog({\n content: loc.msg_deletequoteproduct.format(product.name),\n buttons: [\n new enums.DialogButton(loc.ok, _tools.icons.success, function (args) {\n var promise = _this.$q.when(true);\n if (!_this.$scope.model.idWorkflow) {\n promise = _this.$scope.executeAction(enums.eWorkflowAction.save);\n }\n return promise.then(function () {\n return _this.api.quotes.deleteQuoteProduct($scope.model.id, product, _this.$rootScope.contentTracker).then(function (r) {\n _this.handleActionResponse(r, enums.eWorkflowAction.modifyProducts);\n });\n });\n }),\n new enums.DialogButton(loc.cancel, _tools.icons.cancel, function (args) {\n })\n ]\n });\n };\n $scope.isActiveQuote = function () {\n return quoteService.quote != null && $scope.model.id == quoteService.quote.id;\n };\n $scope.showCopyToActiveQuoteBtn = function (qp) {\n /** only show this 'copy to active quote' button if we are not in the active quote, and the active quote allows modifying products */\n return (qp.isConfigured\n && !$scope.isActiveQuote() //this quote is not the active quote\n && quoteService.quote\n && quoteService.canModifyProductsOfQuote(quoteService.quote)\n && !_this.$rootScope.isSfdc //this should never happen in CRM integration\n );\n };\n $scope.showCopyToThisQuoteBtn = function (qp) {\n /** only show 'copy to this quote' button if this quote has modify products permissions */\n return (qp.isConfigured\n && $scope.permissions.canModifyProducts);\n };\n $scope.showCopyToNewQuoteBtn = function (qp) {\n return qp.isConfigured && !_this.$rootScope.isSfdc; //creating a new quote in this way would break the CRM integration\n };\n $scope.copyProductToThisQuote = function (qp) {\n _this.quoteService.quote = _this.$scope.model; //make this the active quote\n var copyProduct = function () {\n return quoteService.copyProductToActiveQuote(qp.id).then(function (r) {\n if (quoteService.quote && quoteService.quote.id == $scope.model.id) {\n _this.$state.reload();\n }\n else {\n quoteService.goToQuote();\n }\n });\n };\n if (!_this.$scope.model.idWorkflow && !_this.modelIsClean()) {\n return _this.$scope.executeAction(enums.eWorkflowAction.save).then(copyProduct);\n }\n else {\n return copyProduct();\n }\n };\n $scope.copyProductToActiveQuote = function (qp) {\n return quoteService.copyProductToActiveQuote(qp.id).then(function (r) {\n if (quoteService.quote && quoteService.quote.id == $scope.model.id) {\n _this.$state.reload();\n }\n else {\n quoteService.goToQuote();\n }\n });\n };\n $scope.copyProductToNewQuote = function (qp) {\n return quoteService.copyProductToNewQuote(qp.id).then(function (r) {\n quoteService.goToQuote();\n });\n };\n // $scope.delete = () => {\n // return this.delete().then(() => {\n // // if the quote we're deleting is the active quote, clear it out of the quoteservice\n // if (quoteService.quote && quoteService.quote.id == $scope.model.id) {\n // quoteService.quote = undefined;\n // }\n // });\n // };\n $scope.extNet = function (product) {\n var discount = product.discountPercentage || 0;\n var volumeDiscount = 0;\n var volumeDiscounts = product.volumeDiscounts.sort(function (vd1, vd2) { return vd1.qty - vd2.qty; });\n for (var key in volumeDiscounts) {\n var vd = volumeDiscounts[key];\n if (vd.qty > product.qty)\n break;\n volumeDiscount = vd.disc;\n }\n var nonfixed = Big__default['default'](product.price).minus(Big__default['default'](product.fixedPrice)).times(Big__default['default'](product.qty));\n var ext = nonfixed.plus(Big__default['default'](product.fixedPrice));\n var extNet = ext.minus(ext.times(Big__default['default'](discount).div(100))).minus(ext.times(Big__default['default'](volumeDiscount).div(100)));\n return extNet;\n };\n $scope.margin = function (product) {\n return $scope.extNet(product) - $scope.extCost(product);\n };\n $scope.extCost = function (product) {\n var extCost = Big__default['default'](product.cost)\n .minus(Big__default['default'](product.fixedCost))\n .times(product.qty)\n .plus(Big__default['default'](product.fixedCost));\n return extCost;\n };\n var sum = function (mapFn) {\n var products = $scope.model.products;\n var total = products.reduce(function (previousValue, currentValue, index) {\n var product = products[index];\n var propValue = mapFn(product);\n return previousValue.plus(Big__default['default'](propValue));\n }, Big__default['default'](0));\n return total;\n };\n $scope.totalCost = function () {\n return sum(function (product) { return $scope.extCost(product); });\n };\n $scope.totalExtNet = function () {\n return sum(function (product) { return $scope.extNet(product); });\n };\n $scope.total = function () {\n var extNet = $scope.totalExtNet();\n var discount = $scope.model.discountPercentage || 0;\n var shipping = $scope.model.shipping || 0;\n return extNet.minus(extNet.times(Big__default['default'](discount).div(100))).plus(Big__default['default'](shipping));\n };\n $scope.showFixedPrice = function () {\n return $scope.model.products.some(function (p) { return p.fixedPrice != 0; });\n };\n $scope.openGoalPriceDialog = function (product) {\n var value = Math.round(Number(product ? product.price : $scope.total()) * 100) / 100;\n var undiscountedValue = (product ? product.price : $scope.totalExtNet());\n _this.dialogService.input({\n inputType: enums.eInputDialogType.text,\n value: value,\n msg: \"Please enter the desired goal price for \" + (product ? \"each \" + product.name : \"this quote\") + \".\",\n buttons: [\n new enums.InputDialogButton(loc.ok, _tools.icons.success, function (args) {\n var discount = Number(Big__default['default'](args.value).div(undiscountedValue));\n discount = Math.round((1 - discount) * 10000) / 100;\n if (product) {\n product.discountPercentage = discount;\n }\n else {\n $scope.model.discountPercentage = discount;\n }\n }),\n new enums.InputDialogButton(loc.cancel, _tools.icons.cancel, function (args) {\n })\n ]\n });\n };\n $scope.panes = [\n { title: \"General\", content: \"general\", disabled: false },\n { title: \"Comments\", content: \"comments\", disabled: false },\n { title: \"History\", content: \"history\", disabled: false }\n ];\n $scope.inSteelbrick = function () {\n return (_this.sfdcService.record() && _this.sfdcService.record().attributes.type == \"SBQQ__Quote__c\");\n };\n $scope.searchProducts = function (query) {\n if (!query) {\n return Q.resolve([]);\n }\n return _this.api.products.searchByCategory({\n query: query,\n skip: 0,\n take: 11,\n filters: [\n {\n property: enums.meta.Product.isConfigured.name,\n values: [false]\n }\n ]\n });\n };\n $scope.submitQuickAdd = function (item) {\n if (!item)\n return;\n _this.$scope.binding.quickAddQuery = \"\";\n var addProduct = function () {\n _this.quoteService.quote = _this.$scope.model;\n _this.quoteService.addProduct({\n qty: 1,\n configuredProduct: null,\n idProduct: item.id,\n addLocally: false\n }).then(function () {\n _this.setUpdatedModelInternal(_this.quoteService.quote, false);\n });\n };\n if (_this.$scope.model.name) {\n if (_this.$scope.model.id) {\n addProduct();\n }\n else {\n _this.$scope.executeAction(enums.eWorkflowAction.save).then(addProduct);\n }\n }\n };\n $scope.productSortableOptions = {\n stop: function (e, ui) {\n if (_this.$scope.permissions.canReorderProducts && _this.validate()) {\n // set product order\n for (var i = 0; i < $scope.model.products.length; i++) {\n $scope.model.products[i].order = i;\n }\n //reset the products in view\n _this.$scope.productsInView = [];\n _this.$scope.infiniteScroll();\n if ($scope.model.idWorkflow) { // we are in a workflow so we need to run the action\n _this.$timeout(function () {\n return $scope.executeAction(enums.eWorkflowAction.reorderProducts);\n }, 0);\n }\n }\n },\n disabled: true,\n handle: \".kb-grip\"\n };\n $scope.executeAction = function (actionType, modifiedProduct, idCustomAction) {\n if (modifiedProduct === void 0) { modifiedProduct = null; }\n if (idCustomAction === void 0) { idCustomAction = 0; }\n var data;\n var url = \"/api/quotes/\" + actionType;\n var method = \"POST\";\n var getDataDeferred = _this.$q.defer();\n if (!_this.validate() && !_this.$rootScope.context.companySettings.allowInvalidQuotesInWorkflow &&\n actionType != enums.eWorkflowAction.reject &&\n actionType != enums.eWorkflowAction.save &&\n actionType != enums.eWorkflowAction.deleter) {\n _this.promptUserToFixErrors();\n return;\n }\n if (!$scope.model.externalId &&\n _this.sfdcService.record() &&\n _this.sfdcService.record().attributes.type == \"KBMAX__Quote__c\") { // add the externalId to the quote\n $scope.model.externalId = _this.sfdcService.record().Id;\n }\n $scope.model.headerValues = $scope.defConfig.getConfiguredProduct();\n if (actionType == enums.eWorkflowAction.save) {\n data = $scope.model;\n getDataDeferred.resolve();\n }\n else if (actionType == enums.eWorkflowAction.custom) {\n data = { idQuote: $scope.model.id, idCustomAction: idCustomAction };\n getDataDeferred.resolve();\n }\n else if (actionType == enums.eWorkflowAction.reject) {\n // build up a scope to drive the dialog ui\n var dialogScope_1 = $scope.$new(true);\n dialogScope_1.model = {\n reason: loc.other,\n notes: \"\"\n };\n dialogScope_1.reasons = $scope.model.rejectedReasons;\n _this.dialogService.dialog({\n template: Dirs.view(\"dialog-reject\"),\n scope: dialogScope_1,\n buttons: [\n new enums.DialogButton(loc.continuer, _tools.icons.success, function (args) {\n data = {\n quote: $scope.model,\n reason: dialogScope_1.model.reason,\n notes: dialogScope_1.model.notes\n };\n getDataDeferred.resolve();\n }),\n new enums.DialogButton(loc.cancel, _tools.icons.cancel, function (args) { })\n ]\n });\n }\n else if (actionType == enums.eWorkflowAction.modifyProducts) {\n url = \"/api/quotes/\" + _this.$scope.model.id + \"/product/\" + modifiedProduct.id;\n method = \"PUT\";\n data = modifiedProduct;\n getDataDeferred.resolve();\n }\n else if (actionType == enums.eWorkflowAction.modifyQuoteProductDescription) {\n url = \"/api/quotes/\" + _this.$scope.model.id + \"/product/\" + modifiedProduct.id + \"/description\";\n method = \"PUT\";\n data = modifiedProduct;\n getDataDeferred.resolve();\n }\n else if (actionType == enums.eWorkflowAction.reorderProducts) {\n url = \"/api/quotes/reorderproducts\";\n method = \"POST\";\n data = {\n id: _this.$scope.model.id,\n products: _this.$scope.model.products.map(function (qp) {\n return { id: qp.id, order: qp.order };\n })\n };\n getDataDeferred.resolve();\n }\n else {\n data = $scope.model;\n getDataDeferred.resolve();\n }\n return getDataDeferred.promise.then(function () {\n return _this.$http({\n method: method,\n url: url,\n data: data,\n tracker: _this.$rootScope.contentTracker\n }).then(function (response) {\n return _this.handleActionResponse(response.data, actionType);\n });\n });\n };\n $scope.runFieldAction = function (field) {\n return _this.helper.runRuleContainerAsync(field)\n .then(function () { return _this.runRuleCycleUnit(field.$parentConfigurator, null); })\n .then(function () {\n if (_this.$scope.model.idWorkflow) {\n return _this.$scope.executeAction(enums.eWorkflowAction.modifyQuoteHeader);\n }\n });\n };\n $scope.runAction = function (action) {\n return _this.helper.runRuleContainerAsync(action)\n .then(function () { return _this.runRuleCycleUnit(action.$parentConfigurator, null); });\n };\n $scope.fieldValueChange = function (field) {\n return _this.helper.runRuleContainerAsync(field)\n .then(function () { return _this.runRuleCycleUnit(field.$parentConfigurator, field); })\n .then(function () {\n if (_this.$scope.model.idWorkflow) {\n return _this.$scope.executeAction(enums.eWorkflowAction.modifyQuoteHeader);\n }\n });\n };\n $scope.autoCompleteQuery = function (query, field) {\n return _this.helper.autoCompleteQuery(query, field);\n };\n $scope.autoCompleteGetLabel = function (value, field) {\n return _this.helper.autoCompleteGetLabel(value, field);\n };\n $scope.getCurrencyName = function (iso) {\n var cc = $scope.currencies.find(function (c) { return c.currency.isEqual(iso); });\n return cc ? \"\".concat(cc.name, \" (\").concat(cc.currency, \")\") : iso;\n };\n $scope.validationMessageClicked = function (msg) {\n };\n $scope.translateKbo = function (o, prop) {\n if (o) {\n if (_this.$rootScope.companySettings.defaultLanguage != _this.$rootScope.clientLanguage) {\n if (_this.translationDb.hasOwnProperty(o.id) && _this.translationDb[o.id].hasOwnProperty(prop)) {\n return _this.translationDb[o.id][prop];\n }\n }\n var realProp = prop == \"name\" ? \"$label\" : prop;\n return o[realProp];\n }\n return \"\";\n };\n $scope.infiniteScroll = function () {\n var pageSize = 30;\n var totalCount = $scope.model.products.length;\n var currCount = $scope.productsInView.length;\n if (totalCount > currCount) {\n $scope.productsInView.pushArray($scope.model.products.slice(currCount, currCount + pageSize));\n }\n };\n _this.refreshPermissions();\n _this.helper = new ConfiguratorHelper({\n $http: _this.$http,\n $q: _this.$q,\n api: _this.api,\n dialogService: _this.dialogService,\n ruleService: _this.ruleService,\n tracker: _this.$rootScope.contentTracker,\n $rootScope: _this.$rootScope,\n getRuleArgs: function (c, f) { return _this.getRuleArgs(c, f); },\n showErrors: function () { return (_this.$rootScope.environment != enums.eEnvironment.prod); }\n });\n _this.refreshDrawers();\n _this.setupQuoteHeader();\n _this.validate();\n _this.startConfigurator();\n $scope.$on(\"$destroy\", function () {\n _this.stopValidationTimer();\n });\n // currencies\n _this.api.currencies.companyOptions().then(function (r) {\n $scope.currencies = r;\n });\n var updateCustomers = function () {\n _this.api.customers.search({\n fields: [\"id\", \"name\"],\n sortField: \"name\"\n }).then(function (r) { return $scope.customers = r; });\n };\n var updateContacts = function () {\n if ($scope.model.idCustomer) {\n _this.api.contacts.search({\n filters: [{\n property: \"idCustomer\",\n values: [$scope.model.idCustomer]\n }]\n }).then(function (r) { return $scope.contacts = r; });\n }\n else {\n $scope.contacts.clear();\n }\n };\n if (_this.$rootScope.companySettings.enableCustomersAndContacts && (_this.$scope.permissions.canViewCustomer || _this.$scope.permissions.canModifyCustomer)) {\n updateCustomers();\n }\n $scope.$watch(\"model.idCustomer\", function (newValue, oldValue) {\n updateContacts();\n });\n _this.$scope.infiniteScroll(); //fill in first set of products\n _this.startValidationTimer();\n if (_this.$scope.isNew && _this.$rootScope.isSfdc && !_this.$rootScope.isSfdcCpq) {\n var canvasParams = _this.$rootScope.context.sfdcCanvasRequest.context.environment.parameters;\n if (canvasParams.autoSubmit != null && (canvasParams.autoSubmit == true || canvasParams.autoSubmit.isEqual(\"true\"))) {\n _this.submit();\n }\n else {\n _this.$scope.executeAction(enums.eWorkflowAction.save);\n }\n }\n return _this;\n }\n QuoteController.prototype.client = function (api) {\n return api.quotes;\n };\n QuoteController.prototype.onSuccess = function () {\n this.$state.go(\"kb.quoteEdit\", { id: this.$scope.model.id });\n this.drawerService.pageTitle = this.$scope.model.name;\n // this.registerWebSocket();\n };\n QuoteController.prototype.onDelete = function () {\n // if the quote we're deleting is the active quote, clear it out of the quoteservice\n if (this.quoteService.quote && this.quoteService.quote.id == this.$scope.model.id) {\n this.quoteService.quote = undefined;\n }\n this.$state.go(\"kb.quotes\");\n };\n QuoteController.prototype.webSocketEntityType = function () {\n return \"Quote\";\n };\n QuoteController.prototype.subscribe = function () {\n var _this = this;\n _super.prototype.subscribe.call(this);\n this.signalrService.on(\"productImageChange\", this.productImageChange = function (args) {\n if (args.idQuote == _this.$scope.model.id) {\n _this.$timeout(function () {\n var product = _this.$scope.model.products.find(function (p) { return p.id == args.idQuoteProduct; });\n if (product)\n product.imagePath = args.imagePath;\n }, 0);\n }\n });\n };\n QuoteController.prototype.unsubscribe = function () {\n _super.prototype.unsubscribe.call(this);\n this.signalrService.off(\"productImageChange\", this.productImageChange);\n };\n QuoteController.prototype.setUpdatedModel = function (model) {\n this.setUpdatedModelInternal(model);\n };\n QuoteController.prototype.setUpdatedModelInternal = function (model, refreshComments) {\n if (refreshComments === void 0) { refreshComments = true; }\n this.$scope.model = model;\n this.refreshDrawers();\n // refresh the comments as sometimes they are added server-side (like for rejection reasons)\n if (refreshComments)\n this.$scope.commentListApi.refresh();\n this.refreshPermissions();\n this.$scope.productsInView = [];\n this.$scope.infiniteScroll();\n };\n QuoteController.prototype.setupQuoteHeader = function () {\n var _this = this;\n var configurator = new enums.Configurator(new enums.KbObjectManager(), this.header.configurator);\n configurator.$running = true;\n if (this.$scope.isEdit && this.$scope.model.headerValues) {\n configurator.runConfiguredProduct(this.$scope.model.headerValues, null);\n }\n this.$scope.defConfig = configurator;\n this.$scope.visiblePages = this.$scope.defConfig.pages.filter(function (p) { return p.visible; });\n // setup translationDb\n var trans = this.header.translations.first();\n if (trans) {\n Object.keys(trans.data.objects).forEach(function (key) {\n _this.translationDb[key] = trans.data.objects[key];\n });\n }\n };\n QuoteController.prototype.refreshDrawers = function () {\n var _this = this;\n // TODO: This doesn't work for some reason.\n // if (this.$state.current.controller != kb.quoteController) return;\n this.drawerService.drawers.clear();\n this.$scope.availableProductBuildTypes = [];\n if (this.$scope.model.idWorkflow > 0) {\n var actions = this.$scope.model.allowedActions;\n var hasBuildProductAction_1 = false;\n if (actions) {\n angular.forEach(actions, function (action) {\n if (action.type == enums.eWorkflowAction.modifyCustomer ||\n action.type == enums.eWorkflowAction.modifyDiscount ||\n action.type == enums.eWorkflowAction.modifyName ||\n action.type == enums.eWorkflowAction.addAttachments ||\n action.type == enums.eWorkflowAction.modifyAttachments ||\n action.type == enums.eWorkflowAction.completeBuild ||\n action.type == enums.eWorkflowAction.failBuild ||\n action.type == enums.eWorkflowAction.modifyQuoteHeader ||\n action.type == enums.eWorkflowAction.modifyCurrency ||\n action.type == enums.eWorkflowAction.reorderProducts ||\n action.type == enums.eWorkflowAction.modifyQuoteProductDescription ||\n action.type == enums.eWorkflowAction.modifyShipping) ;\n else if (action.type == enums.eWorkflowAction.modifyProducts) {\n // unshift so addProducts is always at the left\n _this.drawerService.drawers.unshift({\n icon: _tools.icons.products,\n label: loc.addproduct,\n visible: true,\n command: function () {\n // set the active quote\n _this.quoteService.quote = _this.$scope.model;\n _this.$state.go(\"kb.products\");\n }\n });\n }\n else if (action.type == enums.eWorkflowAction.buildQuoteProduct) {\n _this.$scope.availableProductBuildTypes.push(action.buildType);\n hasBuildProductAction_1 = true;\n }\n else {\n var icon = action.type == enums.eWorkflowAction.custom ? action.icon : _tools.icons[action.type];\n var actionName = action.type == enums.eWorkflowAction.custom ?\n action.name\n : loc[action.type] || action.type;\n _this.drawerService.addDrawer(icon, actionName, function () {\n _this.$scope.executeAction(action.type, null, action.idCustomAction);\n });\n }\n });\n if (hasBuildProductAction_1) {\n this.api.quotes.getProductBuildTypes(this.$scope.model.id).then(function (result) {\n result.value.forEach(function (pbt) {\n _this.$scope.productBuildTypes[pbt.idProduct] = pbt.idBuildTypes;\n });\n });\n }\n }\n }\n else {\n if (this.$scope.isEdit) {\n var drAddProduct = this.drawerService.addDrawer(_tools.icons.products, loc.addproduct, this.$scope.addProduct);\n if (!this.$rootScope.isSfdc) {\n var drDelete = this.drawerService.addDrawer(_tools.icons.deleter, loc.deleter, this.$scope.delete);\n }\n }\n var drSave = this.drawerService.addDrawer(_tools.icons.save, loc.save, function () {\n _this.validate();\n if (_this.$scope.model.name) {\n _this.$scope.executeAction(enums.eWorkflowAction.save).then(function () {\n if (_this.$state.current.data.viewType == enums.eViewType.new &&\n _this.$rootScope.user.id == AuthService.ANONYMOUS_USER_ID) {\n // Anonymous users need to immediately activate this newly saved quote, \n // since otherwise they'll not have access to it ever again.\n _this.quoteService.quote = _this.$scope.model;\n }\n });\n }\n });\n var drSubmit_1 = this.drawerService.addDrawer(_tools.icons.play, loc.submit, function () {\n drSubmit_1.disabled = true;\n _this.submit();\n });\n }\n var last = this.drawerService.drawers.last();\n if (last)\n last.endGroup = true;\n if (this.$rootScope.isSfdc && !this.$rootScope.isSfdcCpq && this.$scope.model.externalId) {\n var drPrimary = void 0;\n if (this.$scope.isEdit &&\n this.sfdcService.record().KBMAX__Opportunity__c &&\n !this.sfdcService.record().KBMAX__Primary__c) {\n drPrimary = this.drawerService.addDrawer(_tools.icons.approve, \"Make Primary\", function () {\n var p = _this.sfdcService.makePrimaryQuote(_this.$scope.model);\n _this.dialogService.alert({\n promise: p,\n msg: \"Setting \" + _this.$scope.model.name + \" as primary quote\",\n successMsg: _this.$scope.model.name +\n \" has successfully been made the primary quote of the opportunity\"\n });\n _this.refreshDrawers();\n });\n drPrimary.startGroup = true;\n }\n // add an sfdc 'out' button to take us back to the sfdc quote (or opportunity) \n var drDone = this.drawerService.addDrawer(_tools.icons.success, loc.done, function () {\n /*if sfdc passed in a \"navigateTo\" id parameter, then we go there on done\n if not, then we go to the sfdc quote object. You can use this for example\n to go back to the opportunity instead of the quote */\n var canvasParams = _this.$rootScope.context.sfdcCanvasRequest.context.environment.parameters;\n if (canvasParams.navigateTo != null) {\n _this.sfdcService.navigateToObject(canvasParams.navigateTo);\n }\n else {\n _this.sfdcService.navigateToObject(_this.$scope.model.externalId);\n }\n });\n if (!drPrimary)\n drDone.startGroup = true;\n }\n else if (this.$rootScope.isSfdc && this.$scope.inSteelbrick()) {\n // add an sfdc 'out' button to take us back to the sfdc quote (or opportunity) \n var drDone = this.drawerService.addDrawer(_tools.icons.success, loc.done, function () {\n _this.sfdcService.sendMessage({ name: \"goToSteelbrickQuote\", data: _this.sfdcService.record().Id });\n });\n }\n };\n QuoteController.prototype.canUserPerformAction = function (actionType) {\n return this.$scope.model.allowedActions.some(function (a) { return a.type == actionType; });\n };\n QuoteController.prototype.refreshPermissions = function () {\n if (this.$scope.model.idWorkflow) {\n this.$scope.permissions = {\n canModifyName: this.canUserPerformAction(enums.eWorkflowAction.modifyName),\n canModifyCustomer: this.canUserPerformAction(enums.eWorkflowAction.modifyCustomer),\n canModifyDiscount: this.canUserPerformAction(enums.eWorkflowAction.modifyDiscount),\n canModifyProducts: this.canUserPerformAction(enums.eWorkflowAction.modifyProducts),\n canAddAttachments: this.canUserPerformAction(enums.eWorkflowAction.addAttachments),\n canModifyQuoteHeader: this.canUserPerformAction(enums.eWorkflowAction.modifyQuoteHeader),\n canModifyAttachments: this.canUserPerformAction(enums.eWorkflowAction.modifyAttachments),\n canModifyCurrency: this.canUserPerformAction(enums.eWorkflowAction.modifyCurrency),\n canModifyShipping: this.canUserPerformAction(enums.eWorkflowAction.modifyShipping),\n canReorderProducts: this.canUserPerformAction(enums.eWorkflowAction.reorderProducts),\n canViewQuoteHeader: this.$scope.model.userViewPermissions.some(function (a) {\n return a.permission == enums.eViewPermission.viewQuoteHeader;\n }),\n canViewDiscount: this.$scope.model.userViewPermissions.some(function (a) {\n return a.permission == enums.eViewPermission.viewDiscount;\n }),\n canViewCost: this.$scope.model.userViewPermissions.some(function (a) {\n return a.permission == enums.eViewPermission.viewCost;\n }),\n canViewPricing: this.$scope.model.userViewPermissions.some(function (a) {\n return a.permission == enums.eViewPermission.viewPricing;\n }),\n canViewCustomer: this.$scope.model.userViewPermissions.some(function (a) {\n return a.permission == enums.eViewPermission.viewCustomer;\n }),\n canViewCurrency: this.$scope.model.userViewPermissions.some(function (a) {\n return a.permission == enums.eViewPermission.viewCurrency;\n }),\n canViewShipping: this.$scope.model.userViewPermissions.some(function (a) {\n return a.permission == enums.eViewPermission.viewShipping;\n }),\n canModifyQuoteProductDescription: this.canUserPerformAction(enums.eWorkflowAction.modifyQuoteProductDescription),\n canViewQuoteProductDetails: this.$scope.model.userViewPermissions.some(function (a) {\n return a.permission == enums.eViewPermission.viewQuoteProductDetails;\n })\n };\n }\n else {\n this.$scope.permissions = {\n canModifyName: true,\n canModifyProducts: true,\n canModifyCustomer: this.$rootScope.user.canSetQuoteCustomer,\n canModifyDiscount: this.$rootScope.user.canSetQuoteDiscount,\n canAddAttachments: this.$rootScope.user.canAddAttachments,\n canModifyAttachments: this.$rootScope.user.canModifyAllAttachments,\n canModifyShipping: this.$rootScope.user.canSetQuoteShipping,\n canModifyQuoteHeader: true,\n canModifyCurrency: this.$rootScope.user.canSetQuoteCurrency,\n canReorderProducts: true,\n canViewQuoteHeader: this.$rootScope.user.canViewQuoteHeader,\n canViewDiscount: this.$rootScope.user.canViewQuoteDiscount,\n canViewCost: this.$rootScope.user.canViewCost,\n canViewPricing: this.$rootScope.user.canViewPrices,\n canViewCustomer: this.$rootScope.user.canViewQuoteCustomer || this.$rootScope.user.canSetQuoteCustomer,\n canViewCurrency: this.$rootScope.user.canViewQuoteCurrency,\n canViewShipping: this.$rootScope.user.canViewQuoteShipping,\n canModifyQuoteProductDescription: this.$rootScope.user.canSetQuoteProductDescription,\n canViewQuoteProductDetails: true\n };\n }\n this.$scope.productSortableOptions.disabled = !this.$scope.permissions.canReorderProducts;\n if (!this.$scope.permissions.canViewQuoteHeader) {\n this.$scope.selectedTab = null;\n }\n };\n QuoteController.prototype.validate = function () {\n var _this = this;\n var model = this.$scope.model;\n this.$scope.validationMessages = [];\n this.$scope.v.validation = {\n products: {}\n };\n var validation = this.$scope.v.validation;\n var result = true;\n if (!model.name) {\n this.$scope.validationMessages.push({\n messageType: enums.eValidationType.error,\n message: \"Quote is missing a name\",\n propertyName: \"name\",\n object: {\n name: \"Quote\"\n }\n });\n validation.name = \"Please enter a name\";\n result = false;\n }\n var productError = function (index, field, msg, includeInValidationMessages) {\n if (includeInValidationMessages === void 0) { includeInValidationMessages = true; }\n if (!validation.products[index])\n validation.products[index] = {};\n validation.products[index][field] = msg;\n if (includeInValidationMessages) {\n _this.$scope.validationMessages.push({\n messageType: enums.eValidationType.error,\n message: msg,\n propertyName: \"Product \" + model.products[index].name,\n object: {\n id: model.products[index].id.toString(),\n name: \"Product \" + model.products[index].name\n }\n });\n }\n result = false;\n };\n var getErrors = function (configProd, name) {\n if (configProd.validationMessages) {\n configProd.validationMessages.forEach(function (err) { return _this.$scope.validationMessages.push(err); });\n }\n if (configProd.configurators) {\n configProd.configurators.forEach(function (c) { return getErrors(c); });\n }\n };\n model.headerValues = this.$scope.defConfig.getConfiguredProduct();\n getErrors(model.headerValues);\n model.products.forEach(function (product, i) {\n if (product.isConfigured && product.configuredProduct.hasErrors) {\n productError(i, \"name\", \"Please correct the configurator errors.\", false);\n getErrors(product.configuredProduct, \"Product \" + product.name);\n }\n if (!product.allowFractionalQty && product.qty % 1 != 0) {\n productError(i, \"qty\", \"Must be whole number\");\n }\n var maxDiscount = Math.min(product.maxDiscountPercentage, 100);\n if (product.discountPercentage > maxDiscount) {\n productError(i, \"discountPercentage\", \"Must be less than \" + maxDiscount + \"%\");\n }\n if (product.maxQty && product.qty > product.maxQty) {\n productError(i, \"qty\", \"Limited to \" + product.maxQty);\n }\n if ((product.minQty && product.qty < product.minQty) || product.qty < 1) {\n productError(i, \"qty\", \"Must be at least \" + Math.max(product.minQty, 1));\n }\n });\n return result &&\n (!model.headerValues ||\n !model.headerValues.validationMessages ||\n !model.headerValues.validationMessages.some(function (m) { return m.messageType == enums.eValidationType.error; }));\n };\n QuoteController.prototype.submit = function () {\n var _this = this;\n /*if (this.$rootScope.user.id == authService.ANONYMOUS_USER_ID) {\n this.dialogService.alert({\n type: eAlertType.info,\n msg: \"Before you can submit this quote, please login or register.\"\n });\n \n this.$rootScope.user = null;\n this.$rootScope.$broadcast(kb.events.loginRequested);\n this.submitQuotePending = true;\n return;\n }*/\n this.$scope.model.headerValues = this.$scope.defConfig.getConfiguredProduct();\n if (this.validate() ||\n this.$rootScope.context.companySettings.allowInvalidQuotesInWorkflow) {\n this.$scope.executeAction(enums.eWorkflowAction.submit).then(function () {\n _this.$location.url(\"/quotes/\" + _this.$scope.model.id);\n _this.bypassUnsavedConfirmation = true;\n });\n }\n else\n this.promptUserToFixErrors();\n };\n QuoteController.prototype.runRuleCycleUnit = function (config, field, bubble) {\n var _this = this;\n // Skip the entire cycle if user can't view the quote header, since doing so is wasteful.\n if (!this.$scope.permissions.canViewQuoteHeader)\n return this.$q.all([]);\n var ruleArgs = this.getRuleArgs(config, field);\n var runRules = this.helper.runSelects(config)\n // value rules\n .then(function () {\n return _this.helper.runRuleTypeAsync(config, enums.eRuleType.value, ruleArgs);\n }).then(function () {\n // reset $fieldsDirty of this configurator so it doesn't affect \n // a parent's decision on whether to run the child's rules\n return config.$fieldsDirty = false;\n }).then(function () {\n return _this.runValidationRule(config, ruleArgs);\n }).then(function () {\n return _this.helper.runRuleTypeAsync(config, enums.eRuleType.visibility, ruleArgs);\n }).then(function () {\n _this.$scope.visiblePages = config.pages.filter(function (p) { return p.visible; });\n if (!_this.$scope.model.idWorkflow &&\n _this.$scope.defConfig.hasQuoteRule) {\n // run the quote rule if we are not in a workflow \n // (in a workflow it get's run the by the action on the server)\n _this.$scope.model.headerValues = _this.$scope.defConfig.getConfiguredProduct();\n return _this.api.quotes.runQuoteHeaderRule(_this.$scope.model, _this.$rootScope.contentTracker).then(function (q) {\n _this.setUpdatedModelInternal(q, false);\n });\n }\n });\n return runRules;\n };\n QuoteController.prototype.getRuleArgs = function (config, changedField) {\n var ruleArgs = new QuoteHeaderRuleArgs(this);\n ruleArgs.user = this.$rootScope.user;\n ruleArgs.environment = this.$rootScope.environment;\n ruleArgs.baseUrl = this.$rootScope.context.baseUrl;\n ruleArgs.configurator = config;\n ruleArgs.kom = config.$manager;\n ruleArgs.parentKom = config.$parentConfigurator ? config.$parentConfigurator.$manager : null;\n ruleArgs.changedField = changedField;\n ruleArgs.quote = this.$scope.model;\n ruleArgs.logs = new _rules.ClientLogger();\n ruleArgs.clientLanguage = this.$rootScope.clientLanguage;\n if (this.$rootScope.context.sfdcCanvasRequest) {\n // combine query string parameters with sfdc parameters\n ruleArgs.parameters = _tools.Utils.extend(this.$rootScope.context.sfdcCanvasRequest.context.environment.parameters, this.$location.search());\n }\n else {\n ruleArgs.parameters = this.$location.search();\n }\n return ruleArgs;\n };\n /**\n * starts a configurator by loading any tables it references and running the rules once\n * @param config\n */\n QuoteController.prototype.startConfigurator = function () {\n var _this = this;\n var tableIds = this.header.references.filter(function (r) { return r.type.isEqual(\"Table\"); }).map(function (r) { return r.id; });\n return this.helper.downloadTables(tableIds)\n .then(function () { return _this.runRuleCycleUnit(_this.$scope.defConfig, null); });\n };\n QuoteController.prototype.startValidationTimer = function () {\n var _this = this;\n if (!this._stopValidationTimer) {\n this._stopValidationTimer = this.$interval(function () {\n _this.validate();\n }, 1000);\n }\n };\n QuoteController.prototype.stopValidationTimer = function () {\n this.$interval.cancel(this._stopValidationTimer);\n this._stopValidationTimer = null;\n };\n QuoteController.prototype.handleActionResponse = function (result, actionType) {\n this.setUpdatedModelInternal(result, false);\n if (actionType == enums.eWorkflowAction.submit\n && !this.$rootScope.isSfdc\n && !result.allowedActions.some(function (a) { return a.type == enums.eWorkflowAction.modifyProducts; }) //only clear the active quote if the user no longer has modify product permissions\n ) {\n this.quoteService.quote = null;\n }\n else {\n // if this is the active quote, then refresh the active quote data to keep it in sync\n if (this.quoteService.quote && result && this.quoteService.quote.id === result.id) {\n this.quoteService.quote = result;\n }\n }\n if (this.$scope.isNew) { // change to edit edit screen if we were on the new screen before\n this.quoteService.quote = result;\n this.$state.go(\"kb.quoteEdit\", { id: this.$scope.model.id });\n }\n else {\n this.refreshDrawers();\n }\n // refresh the comments as sometimes they are added server-side (like for rejection reasons)\n this.$scope.commentListApi.refresh();\n this.refreshPermissions();\n this.validate();\n this.markChangesClean();\n };\n QuoteController.prototype.revertToClean = function () {\n this.setUpdatedModelInternal(angular.copy(this.cleanModel), false);\n };\n QuoteController.prototype.promptUserToFixErrors = function () {\n this.dialogService.alert({ type: enums.eAlertType.error, template: Dirs.view(\"alert-quote-errors\") });\n };\n QuoteController.prototype.runValidationRule = function (config, ruleArgs) {\n config.preValidate(); // call internal validation for fields\n return this.helper.runRuleTypeAsync(config, enums.eRuleType.validation, ruleArgs).then(function () {\n config.isValid(); //force recalculation of $valid property\n });\n };\n QuoteController = __decorate([\n NgView({\n token: Token.QuoteView,\n inherit: [Token.CrudView],\n dependencies: [\n Token.Header,\n Token.QuoteService,\n Token.SfdcService,\n Token.RuleService,\n Token.$Filter,\n Token.$Timeout,\n Token.$Interval,\n Token.$Location,\n Token.UploadService,\n Token.KbService,\n Token.StorageService\n ],\n resolves: [\n {\n name: \"model\",\n dependencies: [\n Token.$StateParams,\n Token.AuthService,\n Token.QuoteService\n ],\n fn: function ($stateParams, authService, quoteService) {\n return authService.authPromise.then(function () {\n if ($stateParams.id) {\n return quoteService.getQuoteById($stateParams.id);\n }\n else {\n return quoteService.getNewQuote();\n }\n });\n }\n },\n {\n name: \"header\",\n dependencies: [\n Token.AuthService,\n Token.ApiService\n ],\n fn: function (authService, api) {\n return authService.authPromise.then(function () {\n return api.quoteHeaders.getDefault();\n });\n }\n }\n ]\n })\n ], QuoteController);\n return QuoteController;\n }(CrudController));\n\n var QuotesController = /** @class */ (function (_super) {\n __extends(QuotesController, _super);\n function QuotesController($scope, agg, $rootScope, upload, quoteService, storageService) {\n var _this = _super.call(this, $scope, agg) || this;\n _this.upload = upload;\n _this.quoteService = quoteService;\n _this.storageService = storageService;\n agg.drawerService.setHelpUrl('Quotes');\n agg.drawerService.pageType = loc.quotes;\n agg.drawerService.pageIcon = _tools.icons.quote;\n $scope.savedSearchEnabled = true;\n _this.refreshSavedSearches();\n if (_this.agg.$rootScope.company.useDatabaseSearch) {\n $scope.availableFilters.pushArray([_this.getWhereFieldFilter()]);\n }\n $scope.binding.search.modelType = enums.meta.Quote.$name;\n $scope.modelTypes = [\n { type: enums.meta.Quote.$name, label: 'Quotes', state: 'kb.quotes' },\n { type: enums.meta.QuoteProduct.$name, label: 'Configured Products', state: 'kb.configuredProducts' },\n ];\n $scope.downloadAttachment = function (file) {\n if (file.source == enums.eFileSource.media) {\n window.open(storageService.getMediaUrl(file.filePath));\n }\n else {\n window.open('api/quotes/file/download/' + file.id, '_blank');\n }\n };\n $scope.openProduct = function (idQuote, p) {\n if (p.isConfigured) {\n agg.$state.go('kb.configuredProduct', { id: p.id });\n }\n else {\n agg.$state.go('kb.product', { id: p.idProduct });\n }\n };\n $scope.getFirstProductImage = function (quote) {\n var p = quote.products.find(function (p) { return p.imagePath != null; });\n return p ? p.imagePath : null;\n };\n $scope.fieldChange = function (filter) {\n var field = _this.$scope.filterSource[filter['$key']].find(function (f) { return f.name == filter.fieldName; });\n var fieldType = field ? field.type : enums.eFieldType.text;\n filter.fieldType = fieldType;\n if (fieldType == enums.eFieldType.number) {\n filter.control = enums.eFilterControl.numberRange;\n }\n else if (fieldType == enums.eFieldType.boolean) {\n filter.control = enums.eFilterControl.checkbox;\n }\n else {\n filter.control = enums.eFilterControl.text;\n }\n };\n agg.drawerService.addDrawer(_tools.icons.add, loc.add, function () { return agg.$state.go('kb.quoteNew'); });\n if ($rootScope.companySettings.enableQuoteImport) {\n agg.drawerService.addDrawer(_tools.icons.upload, 'Import', function () { return _this.import(); });\n }\n agg.drawerService.addDrawer(_tools.icons.clone, loc.clone, function () { return _this.clone(); });\n agg.drawerService.addDrawer(_tools.icons.deleter, loc.deleter, function () { return _this.deleteItems(); });\n return _this;\n }\n QuotesController.prototype.import = function () {\n var _this = this;\n this.upload.promptUserToChooseFile().then(function (file) {\n var formData = new FormData();\n formData.append('file', file);\n _this.upload.uploadFile(formData, '/api/quotes/import').then(function (r) {\n _this.agg.$state.go('kb.quoteEdit', { id: r.id });\n });\n });\n };\n QuotesController.prototype.client = function (api) {\n return api.quotes;\n };\n QuotesController.prototype.newSearch = function () {\n return {\n modelType: enums.meta.Quote.$name,\n sortField: enums.meta.Quote.modifiedDate.name,\n descending: true,\n filters: this.getFiltersFromMeta(enums.meta.Quote.$name, true),\n roles: [],\n };\n };\n QuotesController.prototype.onItemsDeleted = function (items) {\n //empty out the active quote if we just deleted it\n for (var _i = 0, items_1 = items; _i < items_1.length; _i++) {\n var q = items_1[_i];\n if (q && this.quoteService.quote && q.id == this.quoteService.quote.id) {\n this.quoteService.quote = null;\n }\n }\n };\n QuotesController.prototype.getWhereFieldFilter = function () {\n return {\n type: enums.eFilterType.headerValue,\n label: 'Where Header Field',\n fieldName: null,\n control: enums.eFilterControl.none,\n sourceType: enums.eFilterSource.headerFields,\n values: [null],\n };\n };\n QuotesController = __decorate([\n NgView({\n token: Token.QuotesView,\n inherit: [Token.SearchView],\n dependencies: [Token.$RootScope, Token.UploadService, Token.QuoteService, Token.StorageService],\n })\n ], QuotesController);\n return QuotesController;\n }(SearchController));\n\n var ChangePasswordController = /** @class */ (function (_super) {\n __extends(ChangePasswordController, _super);\n function ChangePasswordController($scope, crudService) {\n var _this = _super.call(this, $scope, crudService, { id: crudService.$stateParams.id }) || this;\n $scope.model = { id: _this.$stateParams.id };\n _this.drawerService.setHelpUrl(null);\n // add drawers\n var drSave = _this.drawerService.addDrawer(_tools.icons.save, loc.save, $scope.save);\n var drCancel = _this.drawerService.addDrawer(_tools.icons.cancel, loc.cancel, $scope.cancel);\n return _this;\n }\n ChangePasswordController.prototype.client = function (api) {\n return api.changePassword;\n };\n ChangePasswordController.prototype.onSuccess = function () {\n this.$state.go(\"kb.admin.userEdit\", { id: this.$stateParams.id });\n };\n ChangePasswordController = __decorate([\n NgView({\n token: Token.ChangePasswordView,\n inherit: [Token.CrudView],\n dependencies: [\n Token.$Scope,\n Token.CrudService\n ]\n })\n ], ChangePasswordController);\n return ChangePasswordController;\n }(CrudController));\n\n (function (eUserActivationMode) {\n eUserActivationMode[\"password\"] = \"password\";\n eUserActivationMode[\"thanks\"] = \"thanks\";\n })(exports.eUserActivationMode || (exports.eUserActivationMode = {}));\n var UserActivationController = /** @class */ (function () {\n function UserActivationController($scope, $rootScope, drawerService, $http, $stateParams, $state) {\n this.$scope = $scope;\n drawerService.setHelpUrl(null);\n $rootScope.user = {\n id: $stateParams.idUser\n };\n $scope.model = {};\n if ($stateParams.pass && ($stateParams.pass.toLowerCase() == \"true\")) {\n $scope.mode = exports.eUserActivationMode.password;\n $scope.isNew = $stateParams.new && ($stateParams.new.toLowerCase() == \"true\");\n }\n else {\n $http.post(\"api/users/activate?idUser=\" + $stateParams.idUser +\n \"&activationGuid=\" + $stateParams.activationGuid +\n \"&password=\", { tracker: $rootScope.contentTracker }).then(function (r) {\n $scope.mode = exports.eUserActivationMode.thanks;\n }, function (r) {\n $scope.validation = CrudController.prototype.getValidationObject(r.data, r.status);\n });\n }\n $scope.validation = {};\n $scope.save = function () {\n $scope.validation = {};\n if ($scope.model.password != $scope.model.confirmPassword) {\n $scope.validation.confirmPassword = \"Passwords do not match.\";\n }\n if ($scope.isNew && !$scope.model.agreedToPrivacyPolicy) {\n $scope.validation.agreedToPrivacyPolicy = \"Must agree to the privacy policy\";\n }\n if ($scope.validation.confirmPassword || $scope.validation.password)\n return;\n var encodePassword = encodeURIComponent($scope.model.password);\n return $http.post(\"api/users/activate?idUser=\" + $stateParams.idUser +\n \"&activationGuid=\" + $stateParams.activationGuid +\n \"&password=\" + encodePassword +\n \"&agreed=\" + $scope.model.agreedToPrivacyPolicy, { tracker: $rootScope.contentTracker }).then(function (r) {\n $scope.mode = exports.eUserActivationMode.thanks;\n }, function (r) {\n $scope.validation = CrudController.prototype.getValidationObject(r.data, r.status);\n });\n };\n $scope.goToLogin = function () {\n window.location.href = \"/\";\n };\n }\n UserActivationController = __decorate([\n NgView({\n token: Token.UserActivationView,\n dependencies: [\n Token.$Scope,\n Token.$RootScope,\n Token.DrawerService,\n Token.$Http,\n Token.$StateParams,\n Token.$State\n ]\n })\n ], UserActivationController);\n return UserActivationController;\n }());\n\n var UserController = /** @class */ (function (_super) {\n __extends(UserController, _super);\n function UserController($scope, crudService, model, $rootScope, kbService) {\n var _this = _super.call(this, $scope, crudService, model) || this;\n _this.$scope = $scope;\n _this.$rootScope = $rootScope;\n $scope.isReadOnlySso = !$rootScope.context.ssoManualUserManagement && model.isSsoUser;\n _this.drawerService.setHelpUrl(\"Users\");\n _this.$http.get(\"/api/notificationsettings\").then(function (response) {\n $scope.notificationSetting = response.data;\n });\n if ($rootScope.user.isCompanyAdmin) {\n _this.api.channels.search({\n sortField: \"name\"\n }).then(function (channels) {\n $scope.channels = channels.map(function (c) {\n return {\n name: c.name,\n value: c.id.toString()\n };\n });\n $scope.channels.unshift({\n name: \"-None-\",\n value: null\n });\n });\n }\n if (_this.$state.current.data.viewType == enums.eViewType.new) {\n // create a new blank user\n $scope.model = {\n isApproved: true,\n licenseType: enums.eUserLicenseType.internal,\n shipToBillingAddress: true,\n roles: []\n };\n }\n _this.api.roles.search({\n sortField: \"role\",\n }).then(function (r) {\n $scope.roles = r.filter(function (ur) { return ur.id != -1; });\n });\n $scope.resetDeactivation = function () {\n _this.api.users.resetDeactivation(_this.$stateParams.id).then(function () {\n _this.dialogService.alert({\n type: enums.eAlertType.success,\n msg: loc.msg_resetdeactivationcomplete\n });\n });\n };\n $scope.resetPassword = function () {\n _this.api.users.resetPassword(_this.$stateParams.id).then(function () {\n _this.dialogService.alert({\n type: enums.eAlertType.success,\n msg: loc.msg_passwordreset.format($scope.model.email)\n });\n });\n };\n $scope.deleteAndAnonymize = function () {\n _this.dialogService.confirm(\"Are you sure you want to delete and permanently anonymize this user? This cannot be undone!\", function () {\n _this.api.users.deleteAndAnonymize(_this.$stateParams.id).then(function () {\n _this.$state.go(\"kb.admin.users\");\n });\n });\n };\n _this.deleteMsg = loc.msg_deleteuser.format(_this.$scope.model.firstName + \" \" + _this.$scope.model.lastName);\n $scope.canEdit = false;\n $scope.canResetPassword = false;\n $scope.canChangePassword = false;\n // determine whether to show edit buttons\n if (_this.$rootScope.user.id == _this.$stateParams.id) {\n // if (this.$rootScope.user.canModifySelf) {\n _this.$scope.canEdit = true;\n _this.$scope.canChangePassword = true;\n // }\n }\n else {\n if (_this.$rootScope.user.canModifyUsers) {\n _this.$scope.canEdit = true;\n _this.$scope.canResetPassword = true;\n }\n }\n $scope.notificationOptions = kbService.getEnumSelects(enums.eNotificationSetting, \"eNotificationSetting\");\n $scope.pendingApprovalNotificationOptions = [\n {\n name: loc.enotificationsetting_email_title,\n value: enums.eNotificationSetting.email\n },\n {\n name: loc.enotificationsetting_none_title,\n value: enums.eNotificationSetting.none\n },\n {\n name: loc.enotificationsetting_companydefault_title,\n value: enums.eNotificationSetting.companyDefault\n },\n ];\n // add drawers\n var drChangePassword = _this.drawerService.addDrawer(_tools.icons.change, loc.changepassword, function () {\n _this.$state.go(\"kb.changePassword\", { id: $scope.model.id });\n }, $scope.canChangePassword && !$scope.isNew);\n if (!$scope.model.isSsoUser) {\n var drResetPassword = _this.drawerService.addDrawer(_tools.icons.change, loc.resetpassword, $scope.resetPassword, $scope.canResetPassword && !$scope.isNew);\n }\n var drEdit = _this.drawerService.addDrawer(_tools.icons.edit, loc.edit, function () {\n _this.$state.go(\"kb.admin.userEdit\", { id: $scope.model.id });\n }, $scope.canEdit && $scope.isView);\n var drDelete = _this.drawerService.addDrawer(_tools.icons.deleter, loc.deleter, $scope.delete, $scope.canEdit && !$scope.isNew);\n var drDeleteAndAnonymize = _this.drawerService.addDrawer(_tools.icons.anonymize, loc.deleteandanonymize, $scope.deleteAndAnonymize, $scope.canEdit && !$scope.isNew);\n var drResetDeactivations = _this.drawerService.addDrawer(_tools.icons.action, loc.resetdeactivationtimer, $scope.resetDeactivation, $rootScope.companySettings.accountIdleExpirationInDays > 0 && $scope.isEdit && $rootScope.context.user.canModifyUsers);\n var drSave = _this.drawerService.addDrawer(_tools.icons.save, loc.save, $scope.save, $scope.isEdit || $scope.isNew);\n var drCancel = _this.drawerService.addDrawer(_tools.icons.cancel, loc.cancel, $scope.cancel, $scope.isEdit || $scope.isNew);\n return _this;\n }\n UserController.prototype.client = function (api) {\n return api.users;\n };\n UserController.prototype.waitForRefresh = function () {\n return true;\n };\n UserController.prototype.onSuccess = function () {\n if (this.$rootScope.user.isCompanyAdmin) {\n this.$state.go(\"kb.admin.users\");\n }\n else {\n this.$state.go(\"kb.products\");\n }\n };\n UserController.prototype.onDelete = function () {\n this.$state.go(\"kb.admin.users\");\n };\n UserController = __decorate([\n NgView({\n token: Token.UserView,\n inherit: [Token.CrudView],\n dependencies: [\n Token.$RootScope,\n Token.KbService\n ]\n })\n ], UserController);\n return UserController;\n }(CrudController));\n\n angular.module('appTemplates', []);\n var kbapp = angular.module(\"kbapp\", [\n \"ngAnimate\",\n \"ngCookies\",\n \"ngSanitize\",\n \"ui.router\",\n \"ajoslin.promise-tracker\",\n \"ui.sortable\",\n \"oc.lazyLoad\",\n \"appTemplates\",\n \"text-mask\"\n // \"jcs.angular-http-batch\"\n ]);\n DI.fillAngularApp(kbapp);\n kbapp.config([\n \"$locationProvider\",\n \"$stateProvider\",\n \"$httpProvider\",\n \"$urlRouterProvider\",\n \"$provide\",\n \"$animateProvider\",\n // \"httpBatchConfigProvider\",\n \"$compileProvider\",\n function ($locationProvider, $stateProvider, $httpProvider, $urlRouterProvider, $provide, $animateProvider, \n // httpBatchConfigProvider: any,\n $compileProvider) {\n // don't use hashbang mode\n $locationProvider.html5Mode(true);\n // Remove the header used to identify ajax call that would prevent CORS from working\n delete $httpProvider.defaults.headers.common[\"X-Requested-With\"];\n // turn off debug classes from angular for performance boost: \n // https://code.angularjs.org/1.5.5/docs/guide/production\n $compileProvider.debugInfoEnabled(false);\n $compileProvider.commentDirectivesEnabled(false);\n $compileProvider.cssClassDirectivesEnabled(false);\n // add our http interceptors\n $httpProvider.interceptors.push(\"securityInterceptor\");\n $httpProvider.interceptors.push(\"cacheBusterInterceptor\");\n // $httpProvider.useApplyAsync(true);\n // $httpProvider.interceptors.push(\"errorInterceptor\");\n $provide.decorator(\"$exceptionHandler\", [\"$delegate\", Token.$Injector.key, function ($delegate, $injector) {\n return (function (exception, cause) {\n $delegate(exception, cause);\n var $telemetryService = $injector.get(Token.TelemetryService.key);\n $telemetryService.trackException(exception);\n });\n }]);\n // when we are on the sfdc url, then go to whatever path the sfdc canvas asked for\n $urlRouterProvider.when(\"/sfdc\", [\n Token.$Location.key, Token.$RootScope.key, Token.$State.key, function ($location, $rootScope, $state) {\n var isSfdcCpq = $rootScope.context.sfdcCanvasRequest.context.environment.parameters.sfdccpq;\n if (isSfdcCpq) {\n var queryString = $location.search();\n if (queryString['idtheme']) {\n return \"/configurators/1?idtheme=\".concat(queryString['idtheme']);\n }\n // we use a dummy configurator id here. The configuratorController will \n // communicate through the canvas to get the real id\n return \"/configurators/1\";\n }\n else {\n var path = $rootScope.context.sfdcCanvasRequest.context.environment.parameters.path;\n path = path || \"/products\";\n return path;\n }\n }\n ]);\n // $urlRouterProvider.when(\"/sfdc/\", handleSfdcUrl);\n // defult to products page\n $urlRouterProvider.when(\"/\", [\n \"$location\", \"$rootScope\", function ($location, $rootScope) {\n if (!$rootScope.company.licenseKbmax && $rootScope.company.license3D) {\n return \"/admin/scenes\";\n }\n return \"/products\";\n }\n ]);\n $urlRouterProvider.when(\"/admin\", [\n \"$location\", \"$rootScope\", function ($location, $rootScope) {\n if ($rootScope.company.licenseKbmax) {\n if ($rootScope.user.canModifyProducts) {\n return \"/admin/configurators\";\n }\n else if ($rootScope.user.canModifyScenes && $rootScope.company.license3D) {\n return \"/admin/scenes\";\n }\n else if ($rootScope.user.canModifyUsers || $rootScope.user.isChannelAdmin) {\n return \"/admin/users\";\n }\n else if ($rootScope.user.canModifyCurrencies) {\n return \"/admin/currencies\";\n }\n else if ($rootScope.user.canModifyMedia) {\n return \"/admin/media\";\n }\n }\n else {\n if ($rootScope.company.license3D) {\n return \"/admin/scenes\";\n }\n }\n return \"/\";\n }\n ]);\n $urlRouterProvider.otherwise(\"/\");\n // only run animations on elements that have a kb-animate class name. \n // This should increase performance.See here: https://docs.angularjs.org/api/ng/provider/$animateProvider\n $animateProvider.classNameFilter(/kb-animate/);\n // register the api batch handler\n // httpBatchConfigProvider.setAllowedBatchEndpoint(\"/api\", \"/api/batch\", {\n // maxBatchedRequestPerCall: 10,\n // minimumBatchSize: 2,\n // batchRequestCollectionDelay: 100,\n // ignoredVerbs: [\"head\"],\n // sendCookies: false,\n // enabled: true,\n // // defaults to this value we currently also support a node js multifetch format as well\n // adapter: \"httpBatchAdapter\"\n // });\n var stateHelper = new StateHelper($stateProvider, exports.eBundle.app);\n // setup states using ui-router library\n stateHelper.addState({\n name: \"kb\",\n url: null,\n abstract: true,\n view: Token.PortalView,\n templateName: \"portal\"\n });\n stateHelper.addState({\n name: \"kb.login\",\n view: Token.LoginView,\n data: { onLoginPage: true }\n });\n stateHelper.addSearchState({\n name: \"kb.products\",\n view: Token.ProductsView,\n url: \"/products?imagemode&search&searchid\"\n });\n // stateHelper.addState({\n // name: \"kb.products\",\n // url: \"/products?cat&sort&q&mode\",\n // view: Token.ProductsView\n // });\n stateHelper.addState({\n name: \"kb.product\",\n url: \"/products/:id\",\n view: Token.ProductView\n });\n stateHelper.addState({\n name: \"kb.productCompare\",\n url: \"/productcompare/:ids\",\n view: Token.ProductCompareView,\n params: {\n ids: { array: true }\n }\n });\n stateHelper.addState({\n name: \"kb.configurator\",\n url: \"/configurators/:id\",\n data: { viewType: enums.eViewType.new },\n view: Token.ConfiguratorView\n });\n stateHelper.addState({\n name: \"kb.configuredProduct\",\n url: \"/quoteproducts/:id\",\n templateName: \"configurator\",\n data: { viewType: enums.eViewType.edit },\n view: Token.ConfiguratorView\n });\n stateHelper.addState({\n name: \"kb.configuratorTest\",\n url: \"/configurators/test/:id\",\n templateName: \"configurator\",\n data: { viewType: enums.eViewType.new, isTest: true },\n view: Token.ConfiguratorView\n });\n stateHelper.addCrudStates({\n name: \"kb.quote\",\n view: Token.QuoteView,\n searchView: Token.QuotesView\n });\n stateHelper.addSearchState({\n name: \"kb.configuredProducts\",\n view: Token.ConfiguredProductsView\n });\n stateHelper.addCrudStates({\n name: \"kb.customer\",\n view: Token.CustomerView,\n searchView: Token.CustomersView\n });\n stateHelper.addCrudStates({\n name: \"kb.contact\",\n view: Token.ContactView,\n searchView: Token.ContactsView\n });\n stateHelper.addState({\n name: \"userActivation\",\n url: \"/users/activate/?idUser&activationGuid&pass&new\",\n view: Token.UserActivationView,\n allowAnonymous: true\n });\n stateHelper.addState({\n name: \"kb.changePassword\",\n url: \"/users/changepassword/:id\",\n data: { viewType: enums.eViewType.new },\n view: Token.ChangePasswordView\n });\n stateHelper.addState({\n name: \"kb.notifications\",\n url: \"/notifications?q&sort&desc\",\n view: Token.NotificationsView\n });\n stateHelper.addState({\n name: \"scene\",\n url: \"/scenes/:id?requestid&&showmove\",\n view: Token.ConfiguratorView,\n templateName: \"configurator\",\n allowAnonymous: true\n });\n $stateProvider.state(\"kb.admin.**\", {\n url: \"/admin\",\n lazyLoad: function ($transition$) {\n var bundleLoader = $transition$.injector().get(Token.BundleLoaderService.key);\n return bundleLoader.load([Token.AdminLib]);\n }\n });\n }\n ]);\n kbapp.run([\n Token.AuthService.key,\n Token.$RootScope.key,\n Token.$Http.key,\n Token.PromiseTracker.key,\n Token.$Location.key,\n Token.$State.key,\n Token.$Window.key,\n Token.ThemeService.key,\n Token.TelemetryService.key,\n Token.QuoteService.key,\n Token.ApiService.key,\n Token.SfdcService.key,\n function (authService, $rootScope, $http, promiseTracker, $location, $state, $window, themeService, telemetryService, quoteService, apiService, sfdcService) {\n // store the state service on the rootscope so views can bind to it\n $rootScope.$state = $state;\n $rootScope.baseUrl = \"https://\" + $(location).attr(\"host\");\n $rootScope.isEpicorEmployee = function () { return $rootScope.user.email.toLowerCase().endsWith(\"@kbmax.com\") || $rootScope.user.email.toLowerCase().endsWith(\"@epicor.com\"); };\n // track if we are in sfdc\n $rootScope.isSfdc = ($rootScope.context.sfdcCanvasRequest != null);\n if ($rootScope.isSfdc) {\n $rootScope.isSfdcCpq = $rootScope.context.sfdcCanvasRequest.context.environment.parameters.sfdccpq;\n var queryString = $location.search();\n $rootScope.isSfdcCustomTheme = false;\n if (queryString[\"idtheme\"]) {\n $rootScope.isSfdcCustomTheme = true;\n }\n }\n // icons array used as a source for some bindings\n $rootScope.icons = Object.values(_tools.icons);\n // set initial window size values\n var $win = $(window);\n $rootScope.windowWidth = $win.width();\n $rootScope.windowHeight = $win.height();\n // track the window size\n $(window).resize(function () {\n if (!$rootScope.$$phase) {\n $rootScope.$apply(function () {\n var $win = $(window);\n $rootScope.windowWidth = $win.width();\n $rootScope.windowHeight = $win.height();\n });\n }\n });\n $rootScope.contentTracker = promiseTracker();\n $rootScope.showSpinner = true;\n $rootScope.loginTracker = promiseTracker();\n $rootScope.infiniteScrollTracker = promiseTracker();\n $rootScope.isHoverSupported = !(matchMedia(\"(hover: none)\").matches);\n $rootScope.isIE = /msie\\s|trident\\//i.test(navigator.userAgent);\n $rootScope.comparedProducts = [];\n $rootScope.recaptchaToken = \"6LfFNOAUAAAAAAreoPer8J4F9qh9WLklfpUAbt28\";\n // hide browser address bar\n window.scrollTo(0, 1);\n $rootScope.translate = function (entity, prop, realProp) {\n if (entity) {\n if ($rootScope.clientLanguage != $rootScope.companySettings.defaultLanguage) {\n if (entity && entity.translations && entity.translations.length) {\n var translation = entity.translations\n .find(function (t) { return t.languageIso == $rootScope.clientLanguage; });\n if (translation) {\n return translation.data[prop];\n }\n }\n }\n return entity[realProp || prop] || entity[prop];\n }\n else {\n return \"\";\n }\n };\n $rootScope.supportsFullscreen = !$rootScope.isSfdcCpq && _tools.Utils.supportsFullscreen();\n $rootScope.toggleFullscreen = function () {\n if ($rootScope.isSfdc) {\n sfdcService.toggleFullscreen();\n }\n else {\n _tools.Utils.toggleFullscreen();\n }\n };\n // track activity\n var lastMove = Date.now();\n var mouseMoveWait = false;\n window.onmousemove = function (event) {\n if (!mouseMoveWait) {\n lastMove = Date.now();\n mouseMoveWait = true;\n setTimeout(function () {\n mouseMoveWait = false;\n }, 200);\n }\n };\n var checkTime = 5 * 60000;\n setInterval(function () {\n if (Date.now() - lastMove < checkTime || $rootScope.user.isAnonymous)\n authService.keepAlive();\n }, checkTime);\n }\n ]);\n\n exports.AdminProductClient = AdminProductClient;\n exports.ApiService = ApiService;\n exports.AssetFilter = AssetFilter;\n exports.AuthService = AuthService;\n exports.AutomationStudioClient = AutomationStudioClient;\n exports.Base64Service = Base64Service;\n exports.BaseController = BaseController;\n exports.BundleLoaderService = BundleLoaderService;\n exports.BytesFilter = BytesFilter;\n exports.CacheBusterInterceptor = CacheBusterInterceptor;\n exports.CategoriesClient = CategoriesClient;\n exports.ChangePasswordController = ChangePasswordController;\n exports.ClaraSceneRuleArgs = ClaraSceneRuleArgs;\n exports.ClaraSceneService = ClaraSceneService;\n exports.ClaraSceneUtilities = ClaraSceneUtilities;\n exports.ClaraViewer = ClaraViewer;\n exports.CompanySettingsClient = CompanySettingsClient;\n exports.ConfiguratorClient = ConfiguratorClient;\n exports.ConfiguratorController = ConfiguratorController;\n exports.ConfiguratorHelper = ConfiguratorHelper;\n exports.ConfiguratorRuleArgs = ConfiguratorRuleArgs;\n exports.ConfiguredProductsController = ConfiguredProductsController;\n exports.ContactController = ContactController;\n exports.ContactsController = ContactsController;\n exports.CrudClient = CrudClient;\n exports.CrudController = CrudController;\n exports.CrudService = CrudService;\n exports.CurrencyClient = CurrencyClient;\n exports.CustomerController = CustomerController;\n exports.CustomersController = CustomersController;\n exports.DI = DI;\n exports.DbTablesClient = DbTablesClient;\n exports.DbWhitelistClient = DbWhitelistClient;\n exports.DbXuserCred = DbXuserCred;\n exports.DeploymentClient = DeploymentClient;\n exports.DialogController = DialogController;\n exports.DialogService = DialogService;\n exports.Directive = Directive;\n exports.Dirs = Dirs;\n exports.DrawerController = DrawerController;\n exports.DrawerService = DrawerService;\n exports.EnumFilter = EnumFilter;\n exports.ErrorInterceptor = ErrorInterceptor;\n exports.FileIconFilter = FileIconFilter;\n exports.FileIdFilter = FileIdFilter;\n exports.ForbiddenReason = ForbiddenReason;\n exports.FxConvertFilter = FxConvertFilter;\n exports.GeneratorClient = GeneratorClient;\n exports.GetFileExtensionFilter = GetFileExtensionFilter;\n exports.GetFilenameFilter = GetFilenameFilter;\n exports.HandlerDb = HandlerDb;\n exports.HasRoleFilter = HasRoleFilter;\n exports.IconFilter = IconFilter;\n exports.ImageSelectHelper = ImageSelectHelper;\n exports.IntegrationSettingsClient = IntegrationSettingsClient;\n exports.InteractionService = InteractionService;\n exports.IsAdminOrCompanyAdminFilter = IsAdminOrCompanyAdminFilter;\n exports.JobsClient = JobsClient;\n exports.Kb3dSceneFunctionRuleArgs = Kb3dSceneFunctionRuleArgs;\n exports.Kb3dSceneRuleArgs = Kb3dSceneRuleArgs;\n exports.Kb3dViewer = Kb3dViewer;\n exports.KbActionSelect = KbActionSelect;\n exports.KbAllowFractions = KbAllowFractions;\n exports.KbAtom = KbAtom;\n exports.KbAttachments = KbAttachments;\n exports.KbAutoComplete = KbAutoComplete;\n exports.KbAvatar = KbAvatar;\n exports.KbAvatarSelect = KbAvatarSelect;\n exports.KbButton = KbButton;\n exports.KbCheckbox = KbCheckbox;\n exports.KbColorPicker = KbColorPicker;\n exports.KbColumn = KbColumn;\n exports.KbComments = KbComments;\n exports.KbContent = KbContent;\n exports.KbCurrencyFilter = KbCurrencyFilter;\n exports.KbDataGrid = KbDataGrid;\n exports.KbDateFilter = KbDateFilter;\n exports.KbDatePicker = KbDatePicker;\n exports.KbDateTimeFilter = KbDateTimeFilter;\n exports.KbDropdown = KbDropdown;\n exports.KbEdit = KbEdit;\n exports.KbEllipsis = KbEllipsis;\n exports.KbExpander = KbExpander;\n exports.KbExpanderGroup = KbExpanderGroup;\n exports.KbField = KbField;\n exports.KbFocus = KbFocus;\n exports.KbForm = KbForm;\n exports.KbIcon = KbIcon;\n exports.KbIf = KbIf;\n exports.KbIfDelay = KbIfDelay;\n exports.KbImageMultiSelect = KbImageMultiSelect;\n exports.KbImageSelect = KbImageSelect;\n exports.KbInclude = KbInclude;\n exports.KbInfiniteScroll = KbInfiniteScroll;\n exports.KbInput = KbInput;\n exports.KbLabel = KbLabel;\n exports.KbList = KbList;\n exports.KbListItem = KbListItem;\n exports.KbMarkdownViewer = KbMarkdownViewer;\n exports.KbMax = KbMax;\n exports.KbMediaList = KbMediaList;\n exports.KbMediaManager = KbMediaManager;\n exports.KbMediaSelect = KbMediaSelect;\n exports.KbMediaViewer = KbMediaViewer;\n exports.KbMenu = KbMenu;\n exports.KbMenuItem = KbMenuItem;\n exports.KbMin = KbMin;\n exports.KbMoney = KbMoney;\n exports.KbMultiAutoComplete = KbMultiAutoComplete;\n exports.KbMultiSelect = KbMultiSelect;\n exports.KbNumberbox = KbNumberbox;\n exports.KbPage = KbPage;\n exports.KbPageTitle = KbPageTitle;\n exports.KbPassword = KbPassword;\n exports.KbPrivacyPolicy = KbPrivacyPolicy;\n exports.KbProgress = KbProgress;\n exports.KbRadio = KbRadio;\n exports.KbResize = KbResize;\n exports.KbRipple = KbRipple;\n exports.KbRise = KbRise;\n exports.KbScope = KbScope;\n exports.KbSearchGrid = KbSearchGrid;\n exports.KbSelect = KbSelect;\n exports.KbService = KbService;\n exports.KbSfdcHeader = KbSfdcHeader;\n exports.KbSlide = KbSlide;\n exports.KbSlider = KbSlider;\n exports.KbSpinner = KbSpinner;\n exports.KbSpinnerElement = KbSpinnerElement;\n exports.KbSrcOnError = KbSrcOnError;\n exports.KbSvgViewer = KbSvgViewer;\n exports.KbTab = KbTab;\n exports.KbTabs = KbTabs;\n exports.KbTextarea = KbTextarea;\n exports.KbTextbox = KbTextbox;\n exports.KbToggle = KbToggle;\n exports.KbTooltip = KbTooltip;\n exports.KbTransclude = KbTransclude;\n exports.KbTree = KbTree;\n exports.KbTreeNode = KbTreeNode;\n exports.KbUiObject = KbUiObject;\n exports.KbUpload = KbUpload;\n exports.KbValidationMessages = KbValidationMessages;\n exports.KineticClient = KineticClient;\n exports.KineticMomClient = KineticMomClient;\n exports.LanguageClient = LanguageClient;\n exports.LastValueCache = LastValueCache;\n exports.LayoutClient = LayoutClient;\n exports.LeadTimeFilter = LeadTimeFilter;\n exports.LocFilter = LocFilter;\n exports.LogIconFilter = LogIconFilter;\n exports.LoginController = LoginController;\n exports.MediaFilter = MediaFilter;\n exports.NgAnimation = NgAnimation;\n exports.NgComponent = NgComponent;\n exports.NgFilter = NgFilter;\n exports.NgInterceptor = NgInterceptor;\n exports.NgService = NgService;\n exports.NgView = NgView;\n exports.NotificationClient = NotificationClient;\n exports.NotificationIconFilter = NotificationIconFilter;\n exports.NotificationsController = NotificationsController;\n exports.NumberFormatFilter = NumberFormatFilter;\n exports.OptionFilterClient = OptionFilterClient;\n exports.PathCache = PathCache;\n exports.PermissionClient = PermissionClient;\n exports.PortalController = PortalController;\n exports.PriceColumnClient = PriceColumnClient;\n exports.PrivacyPolicyController = PrivacyPolicyController;\n exports.ProductClient = ProductClient;\n exports.ProductCompareController = ProductCompareController;\n exports.ProductController = ProductController;\n exports.ProductHistoryClient = ProductHistoryClient;\n exports.ProductsController = ProductsController;\n exports.ProfileImageFilter = ProfileImageFilter;\n exports.QuoteClient = QuoteClient;\n exports.QuoteController = QuoteController;\n exports.QuoteHeaderClient = QuoteHeaderClient;\n exports.QuoteHeaderRuleArgs = QuoteHeaderRuleArgs;\n exports.QuoteProductImageFilter = QuoteProductImageFilter;\n exports.QuoteService = QuoteService;\n exports.QuotesController = QuotesController;\n exports.RangeFilter = RangeFilter;\n exports.RawTextFilter = RawTextFilter;\n exports.RuleService = RuleService;\n exports.SafeFunctionClient = SafeFunctionClient;\n exports.SavedSearchClient = SavedSearchClient;\n exports.SceneCache = SceneCache;\n exports.SceneHistoryClient = SceneHistoryClient;\n exports.SceneViewer = SceneViewer;\n exports.ScenesClient = ScenesClient;\n exports.SearchController = SearchController;\n exports.SearchService = SearchService;\n exports.SecurityInterceptor = SecurityInterceptor;\n exports.SecurityRetryService = SecurityRetryService;\n exports.SelectedBinding = SelectedBinding;\n exports.SfdcService = SfdcService;\n exports.ShadeFilter = ShadeFilter;\n exports.SignalrService = SignalrService;\n exports.SingletonCrudClient = SingletonCrudClient;\n exports.SmartColorFilter = SmartColorFilter;\n exports.StateHelper = StateHelper;\n exports.StorageService = StorageService;\n exports.SvgRuleArgs = SvgRuleArgs;\n exports.TablesClient = TablesClient;\n exports.TelemetryService = TelemetryService;\n exports.TestBuildClient = TestBuildClient;\n exports.ThemeColorFilter = ThemeColorFilter;\n exports.ThemeService = ThemeService;\n exports.ThumbFilter = ThumbFilter;\n exports.Token = Token;\n exports.ToolsClient = ToolsClient;\n exports.TranslateClient = TranslateClient;\n exports.TruncateFilter = TruncateFilter;\n exports.TrustAsHtmlFilter = TrustAsHtmlFilter;\n exports.UploadService = UploadService;\n exports.UserActivationController = UserActivationController;\n exports.UserClient = UserClient;\n exports.UserController = UserController;\n exports.WorkflowsClient = WorkflowsClient;\n exports.kbapp = kbapp;\n\n return exports;\n\n}({}, models, angular, tools, flatpickr, Tether, rules, kb3d, Q, signalR, Big));\n//# sourceMappingURL=app.js.map\n","// tslint:disable:variable-name\r\n\r\nexport class Token {\r\n protected constructor(public key: string) { }\r\n\r\n public static withKey(key: string): Token {\r\n let token = this[key] as Token;\r\n if (!token) token = new Token(key); // throw new Error(`Could not find token for key '${key}'`);\r\n return token;\r\n }\r\n\r\n // libraries\r\n public static AdminLib = new Token(\"adminLib\");\r\n public static Creator = new Token(\"creator\");\r\n public static HandsontableLib = new Token(\"handsontableLib\");\r\n public static HighchartsLib = new Token(\"highchartsLib\");\r\n public static MarkdownDeepLib = new Token(\"markdownDeepLib\");\r\n public static MonacoLoaderLib = new Token(\"monacoLoaderLib\");\r\n public static Recaptcha = new Token(\"Recaptcha\");\r\n public static SnapLib = new Token(\"snapLib\");\r\n public static Viewer = new Token(\"viewer\");\r\n \r\n\r\n // angular built-ins\r\n public static $Animate = new Token(\"$animate\");\r\n public static $Scope = new Token(\"$scope\");\r\n public static $Location = new Token(\"$location\");\r\n public static $Http = new Token(\"$http\");\r\n public static $RootScope = new Token(\"$rootScope\");\r\n public static $Timeout = new Token(\"$timeout\");\r\n public static $Q = new Token(\"$q\");\r\n public static $Window = new Token(\"$window\");\r\n public static $Document = new Token(\"$document\");\r\n public static $Filter = new Token(\"$filter\");\r\n public static $Injector = new Token(\"$injector\");\r\n public static $Interval = new Token(\"$interval\");\r\n public static $TemplateCache = new Token(\"$templateCache\");\r\n public static $TemplateRequest = new Token(\"$templateRequest\");\r\n public static $Compile = new Token(\"$compile\");\r\n public static $Sce = new Token(\"$sce\");\r\n public static $Locale = new Token(\"$locale\");\r\n public static $CookieStore = new Token(\"$cookieStore\");\r\n public static $Sanitize = new Token(\"$sanitize\");\r\n public static PromiseTracker = new Token(\"promiseTracker\");\r\n public static $OcLazyLoad = new Token(\"$ocLazyLoad\");\r\n\r\n // ui router\r\n public static $State = new Token(\"$state\");\r\n public static $Transitions = new Token(\"$transitions\");\r\n public static $StateParams = new Token(\"$stateParams\");\r\n\r\n // resolves\r\n public static Model = new Token(\"model\");\r\n public static ProductResolve = new Token(\"productResolve\");\r\n public static Categories = new Token(\"categories\");\r\n public static Header = new Token(\"header\");\r\n public static SsoGroups = new Token(\"ssoGroups\");\r\n\r\n // animations\r\n public static KbRise = new Token(\".kb-rise\");\r\n\r\n // components\r\n public static KbActionSelect = new Token(\"kbActionSelect\");\r\n public static KbAllowFraction = new Token(\"kbAllowFraction\");\r\n public static KbAtom = new Token(\"kbAtom\");\r\n public static KbAttachments = new Token(\"kbAttachments\");\r\n public static KbAutoComplete = new Token(\"kbAutoComplete\");\r\n public static KbAvatar = new Token(\"kbAvatar\");\r\n public static KbAvatarSelect = new Token(\"kbAvatarSelect\");\r\n public static KbButton = new Token(\"kbButton\");\r\n public static KbCheckbox = new Token(\"kbCheckbox\");\r\n public static KbColorPicker = new Token(\"kbColorPicker\");\r\n public static KbColumn = new Token(\"kbColumn\");\r\n public static KbContent = new Token(\"kbContent\");\r\n public static KbComments = new Token(\"kbComments\");\r\n public static KbDataGrid = new Token(\"kbDataGrid\");\r\n public static KbDatePicker = new Token(\"kbDatePicker\");\r\n public static KbDropdown = new Token(\"kbDropdown\");\r\n public static KbEdit = new Token(\"kbEdit\");\r\n public static KbEllipsis = new Token(\"kbEllipsis\");\r\n public static KbExpander = new Token(\"kbExpander\");\r\n public static KbExpanderGroup = new Token(\"kbExpanderGroup\");\r\n public static KbField = new Token(\"kbField\");\r\n public static KbFieldControl = new Token(\"kbFieldControl\");\r\n public static KbFocus = new Token(\"kbFocus\");\r\n public static KbForm = new Token(\"kbForm\");\r\n public static KbIcon = new Token(\"kbIcon\");\r\n public static KbIf = new Token(\"kbIf\");\r\n public static KbIfDelay = new Token(\"kbIfDelay\");\r\n public static KbImageSelect = new Token(\"kbImageSelect\");\r\n public static KbInclude = new Token(\"kbInclude\");\r\n public static KbInfiniteScroll = new Token(\"kbInfiniteScroll\");\r\n public static KbLabel = new Token(\"kbLabel\");\r\n public static KbList = new Token(\"kbList\");\r\n public static KbListItem = new Token(\"kbListItem\");\r\n public static KbMarkdownViewer = new Token(\"kbMarkdownViewer\");\r\n public static KbMax = new Token(\"kbMax\");\r\n public static KbMediaList = new Token(\"kbMediaList\");\r\n public static KbMediaManager = new Token(\"kbMediaManager\");\r\n public static KbMediaSelect = new Token(\"kbMediaSelect\");\r\n public static KbMediaViewer = new Token(\"kbMediaViewer\");\r\n public static KbMenu = new Token(\"kbMenu\");\r\n public static KbMenuItem = new Token(\"kbMenuItem\");\r\n public static KbMin = new Token(\"kbMin\");\r\n public static KbMoney = new Token(\"kbMoney\");\r\n public static KbMultiAutoComplete = new Token(\"kbMultiAutoComplete\");\r\n public static KbMultiSelect = new Token(\"kbMultiSelect\");\r\n public static KbImageMultiSelect = new Token(\"kbImageMultiSelect\");\r\n public static KbNumberbox = new Token(\"kbNumberbox\");\r\n public static KbOption = new Token(\"kbOption\");\r\n public static KbPage = new Token(\"kbPage\");\r\n public static KbPageTitle = new Token(\"kbPageTitle\");\r\n public static KbPassword = new Token(\"kbPassword\");\r\n public static KbPrivacyPolicy = new Token(\"kbPrivacyPolicy\");\r\n public static KbProgress = new Token(\"kbProgress\");\r\n public static KbRadio = new Token(\"kbRadio\");\r\n public static KbResize = new Token(\"kbResize\");\r\n public static KbRipple = new Token(\"kbRipple\");\r\n public static KbScope = new Token(\"kbScope\");\r\n public static KbSearchGrid = new Token(\"kbSearchGrid\");\r\n public static KbSelect = new Token(\"kbSelect\");\r\n public static KbSfdcHeader = new Token(\"kbSfdcHeader\");\r\n public static KbSlide = new Token(\"kbSlide\");\r\n public static KbSlider = new Token(\"kbSlider\");\r\n public static KbSpinner = new Token(\"kbSpinner\");\r\n public static KbSpinnerElement = new Token(\"kbSpinnerElement\");\r\n public static KbSrcOnError = new Token(\"kbSrcOnError\");\r\n public static KbSvgViewer = new Token(\"kbSvgViewer\");\r\n public static KbTab = new Token(\"kbTab\");\r\n public static KbTabs = new Token(\"kbTabs\");\r\n public static KbTextarea = new Token(\"kbTextarea\");\r\n public static KbTextbox = new Token(\"kbTextbox\");\r\n public static KbToggle = new Token(\"kbToggle\");\r\n public static KbToggleButton = new Token(\"KbToggleButton\");\r\n public static KbTooltip = new Token(\"kbTooltip\");\r\n public static KbTransclude = new Token(\"kbTransclude\");\r\n public static KbTree = new Token(\"kbTree\");\r\n public static KbTreeNode = new Token(\"kbTreeNode\");\r\n public static KbUiObject = new Token(\"kbUiObject\");\r\n public static KbUpload = new Token(\"kbUpload\");\r\n public static KbValidationMessages = new Token(\"kbValidationMessages\");\r\n \r\n \r\n // filters\r\n public static AssetFilter = new Token(\"asset\");\r\n public static BytesFilter = new Token(\"bytes\");\r\n public static EnumFilter = new Token(\"enum\");\r\n public static FileIconFilter = new Token(\"fileIcon\");\r\n public static FileIdFilter = new Token(\"fileId\");\r\n public static FxConvertFilter = new Token(\"fxConvert\");\r\n public static GetFileExtensionFilter = new Token(\"getFileExtension\");\r\n public static GetFilenameFilter = new Token(\"getFilename\");\r\n public static HasRoleFilter = new Token(\"hasRole\");\r\n public static IconFilter = new Token(\"icon\");\r\n public static IsAdminOrCompanyAdminFilter = new Token(\"isAdminOrCompanyAdmin\");\r\n public static KbCurrencyFilter = new Token(\"kbCurrency\");\r\n public static KbDateTimeFilter = new Token(\"kbDateTime\");\r\n public static KbDateFilter = new Token(\"kbDate\");\r\n public static LeadTimeFilter = new Token(\"leadTime\");\r\n public static LocFilter = new Token(\"loc\");\r\n public static LogIconFilter = new Token(\"logIcon\");\r\n public static MediaFilter = new Token(\"media\");\r\n public static NotificationIconFilter = new Token(\"notificationIcon\");\r\n public static NumberFormateFilter = new Token(\"numberFormat\");\r\n public static ProfileImageFilter = new Token(\"profileImage\");\r\n public static QuoteProductImageFilter = new Token(\"quoteProductImage\");\r\n public static RangeFilter = new Token(\"range\");\r\n public static RawTextFilter = new Token(\"rawText\");\r\n public static ShadeFilter = new Token(\"shade\");\r\n public static SmartColorFilter = new Token(\"smartColor\");\r\n public static ThemeColorFilter = new Token(\"themeColor\");\r\n public static ThumbFilter = new Token(\"thumb\");\r\n public static TruncateFilter = new Token(\"truncate\");\r\n public static TrustAsHtmlFilter = new Token(\"trustAsHtml\");\r\n\r\n // interceptors\r\n public static CacheBusterInterceptor = new Token(\"cacheBusterInterceptor\");\r\n public static ErrorInterceptor = new Token(\"errorInterceptor\");\r\n public static SecurityInterceptor = new Token(\"securityInterceptor\");\r\n\r\n // services\r\n public static ApiService = new Token(\"apiService\");\r\n public static AuthService = new Token(\"authService\");\r\n public static Base64Service = new Token(\"base64Service\");\r\n public static BundleLoaderService = new Token(\"bundleLoaderService\");\r\n public static ClaraSceneService = new Token(\"claraSceneService\");\r\n public static CrudService = new Token(\"crudService\");\r\n public static DialogService = new Token(\"dialogService\");\r\n public static DrawerService = new Token(\"drawerService\");\r\n public static KbService = new Token(\"kbService\");\r\n public static QuoteService = new Token(\"quoteService\");\r\n public static RuleService = new Token(\"ruleService\");\r\n public static SearchService = new Token(\"searchService\");\r\n public static SecurityRetryService = new Token(\"securityRetryService\");\r\n public static SfdcService = new Token(\"sfdcService\");\r\n public static SignalRService = new Token(\"signalRService\");\r\n public static StorageService = new Token(\"storageService\");\r\n public static TelemetryService = new Token(\"telemetryService\");\r\n public static ThemeService = new Token(\"themeService\");\r\n public static UploadService = new Token(\"uploadService\");\r\n public static InteractionService = new Token(\"interactionService\");\r\n\r\n // views\r\n public static ContactView = new Token(\"contactView\");\r\n public static ContactsView = new Token(\"contactsView\");\r\n public static CrudView = new Token(\"crudView\");\r\n public static CustomerView = new Token(\"customerView\");\r\n public static CustomersView = new Token(\"customersView\");\r\n public static DialogView = new Token(\"dialogView\");\r\n public static NotificationsView = new Token(\"notificationsView\");\r\n public static DrawerView = new Token(\"drawerView\");\r\n public static LoginView = new Token(\"loginView\");\r\n public static PortalView = new Token(\"portalView\");\r\n public static PrivacyPolicyView = new Token(\"privacyPolicyView\");\r\n public static ConfiguratorView = new Token(\"configuratorView\");\r\n public static ProductView = new Token(\"productView\");\r\n public static ProductsView = new Token(\"productsView\");\r\n public static ProductCompareView = new Token(\"productCompareView\");\r\n public static ConfiguredProductsView = new Token(\"configuredProductsView\");\r\n public static QuoteView = new Token(\"quoteView\");\r\n public static QuotesView = new Token(\"quotesView\");\r\n public static SceneEmbedView = new Token(\"sceneEmbedView\");\r\n public static SearchView = new Token(\"searchView\");\r\n public static ChangePasswordView = new Token(\"changePasswordView\");\r\n public static UserActivationView = new Token(\"userActivationView\");\r\n public static UserView = new Token(\"userView\");\r\n}\r\n","import { Token } from \"@app/di/token\";\r\nimport { BundleLoaderService } from \"@app/services/bundle-loader.service\";\r\nimport { Constructor, IMap } from \"@tools\";\r\n\r\nexport interface INgInjectResolve {\r\n name: string;\r\n dependencies?: Token[];\r\n fn?: Function;\r\n}\r\n\r\nexport interface INgInjectArgs {\r\n token: Token;\r\n /**\r\n * inherit the dependencies and resolves of another object.\r\n * Useful for derived controllers.\r\n */\r\n inherit?: Token[];\r\n dependencies?: Token[];\r\n resolves?: INgInjectResolve[];\r\n libraries?: Token[];\r\n}\r\n\r\nexport interface INgInject {\r\n /**\r\n * The angular type... like service, controller, directive, etc.\r\n */\r\n ngType: string;\r\n token: Token;\r\n dependencies: Token[];\r\n resolves?: INgInjectResolve[];\r\n construct: any[];\r\n resolveObject: { [name: string]: Function };\r\n libraries?: Token[];\r\n addedToApp: boolean;\r\n}\r\n\r\nexport function NgService(args: INgInjectArgs) {\r\n return (target: Constructor) => {\r\n DI.register(\"service\", args, target);\r\n };\r\n}\r\nexport function NgAnimation(args: INgInjectArgs) {\r\n return (target: Constructor) => {\r\n DI.register(\"animation\", args, target);\r\n };\r\n}\r\nexport function NgComponent(args: INgInjectArgs) {\r\n return (target: Constructor) => {\r\n DI.register(\"directive\", args, target);\r\n };\r\n}\r\nexport function NgInterceptor(args: INgInjectArgs) {\r\n return (target: Constructor) => {\r\n DI.register(\"factory\", args, target);\r\n };\r\n}\r\nexport function NgFilter(args: INgInjectArgs) {\r\n return (target: Constructor) => {\r\n DI.register(\"filter\", args, target);\r\n };\r\n}\r\nexport function NgView(args: INgInjectArgs) {\r\n return (target: Constructor) => {\r\n DI.register(\"controller\", args, target);\r\n };\r\n}\r\n\r\nexport class DI {\r\n private static db: IMap = {};\r\n\r\n public static register(ngType: string, args: INgInjectArgs, constructor: Constructor) {\r\n if (DI.db.hasOwnProperty(args.token.key)) {\r\n throw new Error(`A type with key ${args.token.key} has already been registered`);\r\n }\r\n args.dependencies = args.dependencies || [];\r\n args.resolves = args.resolves || [];\r\n args.libraries = args.libraries || [];\r\n\r\n if (args.inherit) {\r\n for (let baseToken of args.inherit) {\r\n let baseInject = DI.get(baseToken);\r\n if (baseInject.dependencies) args.dependencies.unshift(...baseInject.dependencies);\r\n if (baseInject.resolves) args.resolves.unshift(...baseInject.resolves);\r\n if (baseInject.libraries) args.libraries.unshift(...baseInject.libraries);\r\n }\r\n }\r\n\r\n let resolveObject = args.resolves &&\r\n args.resolves\r\n .reduce((p, c) => {\r\n p[c.name] = [].concat(...c.dependencies.map(d => d.key)).concat(c.fn.bind(constructor));\r\n return p;\r\n }, {});\r\n if (args.libraries) {\r\n resolveObject[\"scripts\"] = [Token.BundleLoaderService.key, (bundleLoader: BundleLoaderService) => {\r\n return bundleLoader.load(args.libraries);\r\n }];\r\n }\r\n\r\n let ngInject = {\r\n token: args.token,\r\n ngType,\r\n dependencies: args.dependencies,\r\n resolves: args.resolves,\r\n construct: [].concat(args.dependencies.map(d => d.key)).concat((...a) => new constructor(...a)),\r\n resolveObject: resolveObject,\r\n libraries: args.libraries\r\n } as INgInject;\r\n DI.db[args.token.key] = ngInject;\r\n }\r\n\r\n public static get(token: Token): INgInject {\r\n return DI.db[token.key];\r\n }\r\n\r\n public static fillAngularApp(app: ng.IModule) {\r\n for (let key in DI.db) {\r\n let i = DI.db[key];\r\n if (!i.addedToApp) {\r\n app[i.ngType](i.token.key, i.construct);\r\n i.addedToApp = true;\r\n } \r\n }\r\n }\r\n}\r\n","export enum eBundle{\r\n app = \"app\",\r\n admin = \"admin\"\r\n}\r\n\r\nexport class Dirs {\r\n public static component(name: string, bundle: eBundle = eBundle.app): string {\r\n return this.get(`html/${bundle}/${name}.component.html`);\r\n }\r\n\r\n public static template(name: string, bundle: eBundle = eBundle.app): string {\r\n return this.get(`html/${bundle}/${name}.html`);\r\n }\r\n\r\n public static view(name: string, bundle: eBundle = eBundle.app): string {\r\n return this.get(`html/${bundle}/${name}.view.html`);\r\n }\r\n\r\n public static get(url: string) {\r\n return (window as any).html[url];\r\n }\r\n}\r\n","import { NgService } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { IRuleService } from \"@app/services/rule.service\";\r\nimport { Configurator, eFieldType, eRuleType, Field, IAddModelClickHandlerArgs, IAnimateCameraArgs, IAnimateClipArgs, IClaraSceneRuleArgs, IConstrainCameraArgs, IDraggable, IFrameSceneArgs, IGetNodeArgs, IGetTableRuleArgs, IGetUploadImageNodeArgs, IGhostArgs, IHighlightArgs, IJsResult, ILastValueCache, IPathCache, ISceneAnimationArgs, ISceneApi, ISceneCache, ISceneGetIdArgs, ISceneGetNameArgs, ISceneGetPropertyArgs, ISceneNode, ISceneRuleArgs, ISceneSetPropertyArgs, ISceneSetVisibleArgs, ISceneUtilities, ISelectNodeArgs, IToggleToolArgs, IUploadValue, KbObjectManager } from \"@models\";\r\nimport { ClientLogger, KPromise } from \"@rules\";\r\nimport { Color, Logger, Utils } from \"@tools\";\r\n\r\nexport enum eClaraPropertyType {\r\n string = \"string\",\r\n number = \"number\",\r\n boolean = \"boolean\",\r\n color = \"color\",\r\n reference = \"reference\"\r\n}\r\n\r\nexport enum eHighlightType {\r\n user = \"user\",\r\n hover = \"hover\",\r\n selection = \"selection\"\r\n}\r\n\r\nexport class ClaraSceneUtilities implements ISceneUtilities {\r\n constructor(\r\n public sceneService: ClaraSceneService,\r\n public sceneApi: ISceneApi,\r\n public ruleType: eRuleType,\r\n public idMap?: {},\r\n public nestedSceneId?: string\r\n ) {\r\n\r\n }\r\n public setProperty(args: ISceneSetPropertyArgs) {\r\n args.nestedSceneId = this.nestedSceneId;\r\n args.objectId = this.mapId(args.objectId);\r\n args.value = this.mapId(args.value); // sometimes the value is an id as well (like setting a material reference)\r\n this.sceneService.setProperty(this.sceneApi, args);\r\n if (this.sceneApi.afterSetProperty) this.sceneApi.afterSetProperty(args);\r\n }\r\n public getProperty(args: ISceneGetPropertyArgs) {\r\n args.nestedSceneId = this.nestedSceneId;\r\n args.objectId = this.mapId(args.objectId);\r\n return this.sceneService.getProperty(this.sceneApi, args);\r\n }\r\n public setVisible(args: ISceneSetVisibleArgs) {\r\n args.nestedSceneId = this.nestedSceneId;\r\n args.objectId = this.mapId(args.objectId);\r\n return this.sceneService.setVisibleRecursively(this.sceneApi, args);\r\n }\r\n public frameScene(args?: IFrameSceneArgs) {\r\n return this.sceneService.frameScene(this.sceneApi, args);\r\n }\r\n public animateCamera(args: IAnimateCameraArgs) {\r\n return this.sceneService.animateCamera(this.sceneApi, args);\r\n }\r\n public animate(args: ISceneAnimationArgs) {\r\n args.objectId = this.mapId(args.objectId);\r\n this.sceneService.animate(this.sceneApi, args);\r\n if (this.sceneApi.afterAnimateProperty) this.sceneApi.afterAnimateProperty(args);\r\n }\r\n public animateClip(args: IAnimateClipArgs) {\r\n return this.sceneService.animateClip(this.sceneApi, args);\r\n }\r\n public addModelClickHandler(args: IAddModelClickHandlerArgs) {\r\n args.modelId = this.mapId(args.modelId); \r\n args.addedByRuleType = this.ruleType;\r\n\r\n // we need a unique id for the handler, but in the context of the nested configurator.\r\n if (this.nestedSceneId) {\r\n args.uniqueId = this.nestedSceneId + \"-\" + args.uniqueId;\r\n if (args.hotspotId) {\r\n args.hotspotId = this.nestedSceneId + \"-\" + args.hotspotId;\r\n }\r\n }\r\n if (this.sceneApi.addModelClickHandler) {\r\n return this.sceneApi.addModelClickHandler(args);\r\n }\r\n }\r\n public clearClickHandlers() {\r\n if (this.sceneApi.clickDb) this.sceneApi.clearClickHandlers();\r\n }\r\n public addDraggable(args: IDraggable) {\r\n args.addedByRuleType = this.ruleType;\r\n args.objectId = this.mapId(args.objectId);\r\n this.sceneApi.addDraggable(args);\r\n }\r\n public clearDraggables() {\r\n if (this.sceneApi.draggableDb) this.sceneApi.clearDraggables();\r\n }\r\n public ghost(args: IGhostArgs) {\r\n return this.sceneService.ghost(this.sceneApi, args);\r\n }\r\n public clearGhosts() {\r\n return this.sceneService.clearGhosts(this.sceneApi);\r\n }\r\n public highlight(args: IHighlightArgs) {\r\n return this.sceneService.highlight(this.sceneApi, args, eHighlightType.user);\r\n }\r\n public clearHighlights() {\r\n return this.sceneService.clearHighlightsOfType(this.sceneApi, eHighlightType.user);\r\n }\r\n public select(args: ISelectNodeArgs) {\r\n return this.sceneService.select(this.sceneApi, args);\r\n }\r\n public clearSelection() {\r\n return this.sceneService.clearSelection(this.sceneApi);\r\n }\r\n public getId(args: ISceneGetIdArgs): string {\r\n return this.sceneApi.cache.paths.getId({ name: args.name });\r\n }\r\n\r\n public getName(args: ISceneGetNameArgs): string {\r\n return this.sceneApi.api.scene.get({ id: args.id, property: \"name\" });\r\n }\r\n\r\n protected mapId(id): string {\r\n return this.idMap ? this.idMap[id] || id : id;\r\n }\r\n\r\n public getNode(args: IGetNodeArgs): ISceneNode {\r\n let o = this.sceneService.getQueryObject(this.sceneApi, args.id, null);\r\n let id = this.sceneApi.cache.paths.getId(o);\r\n let name = this.sceneApi.api.scene.get({ id, property: \"name\" });\r\n let t = this.sceneApi.api.scene.get({ id, property: \"type\" });\r\n\r\n return {\r\n id,\r\n name,\r\n type: t\r\n } as ISceneNode;\r\n }\r\n\r\n public getChildNodes(args: IGetNodeArgs): ISceneNode[] {\r\n let children: ISceneNode[] = [];\r\n let o = this.sceneService.getQueryObject(this.sceneApi, args.id, null);\r\n let id = this.sceneApi.cache.paths.getId(o);\r\n if (id) {\r\n // TODO: 2018-01-19 (RH): Had to cast this to due to a type mismatch error in the\r\n // new TS 2.5 compiler.\r\n let childIds: any[] = this.sceneApi.api.scene.filter({ from: id as any } as any) as any;\r\n if (childIds && childIds.length) {\r\n childIds.forEach((childId: string) => {\r\n children.push(this.getNode({ id: childId }));\r\n });\r\n }\r\n }\r\n return children;\r\n }\r\n\r\n public whenAssetsLoaded(): Q.IPromise {\r\n return this.sceneApi.api.sceneIO.whenLoaded();\r\n }\r\n\r\n public getActiveCamera(): string{\r\n return this.sceneApi.api.player.getCamera();\r\n }\r\n}\r\n\r\n/**\r\n * PathCache stores a map between query objects and paths for the V2 player. \r\n * Paths are better because it doesn't result in a search.\r\n * We also store the last set value so we don't keep setting the current value \r\n * over and over which costs with performance.\r\n */\r\nexport class PathCache implements IPathCache {\r\n constructor(public sceneApi: ISceneApi) { }\r\n\r\n private _data = {};\r\n public get(query: clara2.IQueryObject): any[] {\r\n var paths = this.getPaths(query, false) as any[][];\r\n return paths.length ? paths.first() : [];\r\n }\r\n public getId(query: clara2.IQueryObject): string {\r\n var paths = this.getPaths(query, false) as string[];\r\n return paths.length ? paths.first() : null;\r\n }\r\n public getIds(query: clara2.IQueryObject): string[] {\r\n return this.getPaths(query, true) as string[];\r\n }\r\n public getAll(query: clara2.IQueryObject): any[][] {\r\n return this.getPaths(query, true) as any[][];\r\n }\r\n public clear() {\r\n this._data = {};\r\n }\r\n public clearEntriesThatContain(...searchTerms: string[]) {\r\n let keys = Object.keys(this._data);\r\n for (let key of keys) {\r\n for(let term of searchTerms){\r\n if (key.indexOf(term) > -1) {\r\n delete this._data[key];\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n\r\n private getPaths(query: clara2.IQueryObject, forSetAll: boolean): any[][] | string[] {\r\n let key = JSON.stringify(query);\r\n let exists = this._data.hasOwnProperty(key);\r\n if (exists) {\r\n return this._data[key];\r\n } else {\r\n let paths: any[][] = [];\r\n if (forSetAll) {\r\n paths = this.sceneApi.api.scene.filter(query) as any[][];\r\n } else {\r\n let path = this.sceneApi.api.scene.find(query) as any[];\r\n if (path) paths.push(path);\r\n }\r\n if (!paths.length) {\r\n console.warn(\"cannot find object with query: \" + JSON.stringify(query));\r\n } else {\r\n this._data[key] = paths;\r\n }\r\n return paths;\r\n }\r\n }\r\n}\r\n\r\nexport class LastValueCache implements ILastValueCache {\r\n private _data = {};\r\n public get(path: any[]): any {\r\n let key = JSON.stringify(path);\r\n return this._data[key];\r\n }\r\n public set(path: any[], value: any) {\r\n this._data[JSON.stringify(path)] = JSON.stringify(value);\r\n }\r\n public valueEqualTo(path: any[], val: any) {\r\n let key = JSON.stringify(path);\r\n return this._data[key] === JSON.stringify(val);\r\n }\r\n}\r\n\r\nexport class SceneCache implements ISceneCache {\r\n constructor(public sceneApi: ISceneApi) { }\r\n\r\n public paths = new PathCache(this.sceneApi);\r\n public lastValues = new LastValueCache();\r\n}\r\n\r\n@NgService({\r\n token: Token.ClaraSceneService,\r\n dependencies: [\r\n Token.RuleService,\r\n Token.$Q,\r\n ]\r\n})\r\nexport class ClaraSceneService {\r\n constructor(\r\n private ruleService: IRuleService,\r\n private $q: ng.IQService\r\n ) {\r\n\r\n }\r\n\r\n private _vectorProperties: string[] = [\r\n \"translationx\",\r\n \"translationy\",\r\n \"translationz\",\r\n \"rotationx\",\r\n \"rotationy\",\r\n \"rotationz\",\r\n \"scalex\",\r\n \"scaley\",\r\n \"scalez\"\r\n ];\r\n\r\n public NESTED_SCENE_PREFIX = \"kb-nested-\";\r\n\r\n public convertColorForScene(hex: string): { r: number, g: number, b: number } {\r\n // clara expects rgb values from 0 to 1\r\n let color = new Color(hex).toRgb();\r\n color.r = color.r / 255;\r\n color.g = color.g / 255;\r\n color.b = color.b / 255;\r\n return color;\r\n }\r\n\r\n private normalizePropertyValue(sceneApi: ISceneApi, args: ISceneSetPropertyArgs) {\r\n let origValue: any = args.value;\r\n if (args.propertyType && args.propertyType.isEqual(\"Color\")) { // property type is the clara data type, not the snap data type\r\n // if value is already an rgb object, then skip this\r\n if (args.value &&\r\n typeof args.value === \"object\" &&\r\n args.value.hasOwnProperty(\"r\") &&\r\n args.value.hasOwnProperty(\"g\") &&\r\n args.value.hasOwnProperty(\"b\")\r\n ) {\r\n // do nothing\r\n } else if (args.value !== null) {\r\n args.value = this.convertColorForScene(args.value);\r\n }\r\n }\r\n if (this._vectorProperties.indexOf(args.property) > -1) {\r\n let axis = args.property.charAt(args.property.length - 1);\r\n args.property = args.property.substr(0, args.property.length - 1);\r\n\r\n let currentVal = this.getProperty(sceneApi, {\r\n objectId: args.objectId,\r\n name: args.name,\r\n plug: args.plug,\r\n operator: args.operator,\r\n property: args.property,\r\n propertyType: null,\r\n nestedSceneId: args.nestedSceneId\r\n });\r\n\r\n if (currentVal && currentVal.clone) currentVal = currentVal.clone();\r\n currentVal[axis] = origValue;\r\n\r\n args.value = currentVal;\r\n }\r\n }\r\n\r\n public toggleTool(sceneApi: ISceneApi, args: IToggleToolArgs) {\r\n sceneApi.api.commands.updateCommand(args.tool, { enabled: args.enabled });\r\n }\r\n\r\n public constrainCamera(sceneApi: ISceneApi, args: IConstrainCameraArgs) {\r\n let radius: any = args.constrain ? args.radius : null;\r\n sceneApi.api.player.setCameraRadiusConstraint(radius);\r\n }\r\n\r\n /**\r\n * validates that the given string is a valid clara id. Note that clara used to use guids, \r\n * and now uses these: https://github.com/ericelliott/cuid\r\n * so we need to validate for both\r\n * @param id\r\n */\r\n public isClaraId(id: string): boolean {\r\n let cuidRegex = /^c[^\\s-]{8,}$/;\r\n return Utils.isGuid(id) || (cuidRegex.exec(id) != null);\r\n }\r\n\r\n public getParentNodeId(sceneApi: ISceneApi, nodeId: string) {\r\n return sceneApi.api.scene.find({\r\n id: nodeId,\r\n parent: true\r\n } as clara2.IQueryObject) as string;\r\n }\r\n\r\n public getChildNodeIds(sceneApi: ISceneApi, nodeId: string): string[] {\r\n return sceneApi.api.scene.filter({ from: nodeId }) as string[];\r\n }\r\n\r\n public findAncestorNodeId(sceneApi: ISceneApi, nodeId: string, callback: (nodeId: string) => boolean): string {\r\n let parentId = nodeId;\r\n while (parentId) {\r\n if (callback(parentId)) break;\r\n parentId = this.getParentNodeId(sceneApi, parentId);\r\n }\r\n return parentId;\r\n }\r\n\r\n public getProperty(sceneApi: ISceneApi, args: ISceneGetPropertyArgs) {\r\n let axis: string;\r\n if (this._vectorProperties.indexOf(args.property) > -1) {\r\n axis = args.property.charAt(args.property.length - 1);\r\n args.property = args.property.substr(0, args.property.length - 1);\r\n }\r\n\r\n let query: clara2.IQueryObject = this.getQueryObjectFromArgs(sceneApi, args);\r\n // if the item is in a nested scene, we must look for the item only in the nested scene null,\r\n // otherwise regex style sets will be applied to the whole scene\r\n // materials are not nested under the nested scene null so they do not apply & \r\n // from is not needed if doing an id search, so we only use it when doing by name\r\n if (args.nestedSceneId && query.name && !args.operator.equalsAny(\"Physical\", \"Canvas\", \"CanvasText\")) {\r\n query.from = { id: args.nestedSceneId };\r\n }\r\n \r\n let path = sceneApi.cache.paths.get(query);\r\n let result = null;\r\n result = sceneApi.api.scene.get(path);\r\n\r\n if (axis && result) {\r\n result = result[axis];\r\n }\r\n return result;\r\n }\r\n\r\n public setProperty(sceneApi: ISceneApi, args: ISceneSetPropertyArgs) {\r\n this.normalizePropertyValue(sceneApi, args);\r\n\r\n // if this is a reference type, then we need to set the reference property to the id of the referenced item\r\n if (args.propertyType && args.propertyType.isEqual(\"Node\")) {// property type is the clara data type, not the snap data type\r\n if (!this.isClaraId(args.value)) {\r\n args.value = sceneApi.cache.paths.getId({ name: args.value });\r\n }\r\n }\r\n\r\n let query: clara2.IQueryObject = this.getQueryObjectFromArgs(sceneApi, args);\r\n // if the item is in a nested scene, we must look for the item only in the nested scene null,\r\n // otherwise regex style sets will be applied to the whole scene\r\n // materials are not nested under the nested scene null so they do not apply & \r\n // from is not needed if doing an id search, so we only use it when doing by name\r\n if (args.nestedSceneId && query.name && !args.operator.equalsAny(\"Physical\", \"Canvas\", \"CanvasText\")) {\r\n query.from = { id: args.nestedSceneId };\r\n }\r\n\r\n let setAll: boolean = (query.name != null); // we use setAll if this is possibly a regex query\r\n let paths = sceneApi.cache.paths.getAll(query);\r\n paths.forEach(path => {\r\n if (!sceneApi.cache.lastValues.valueEqualTo(path, args.value)) {\r\n sceneApi.api.scene.set(path, args.value);\r\n Logger.logSceneChange(\"set \" + JSON.stringify(args));\r\n sceneApi.cache.lastValues.set(path, args.value);\r\n }\r\n });\r\n }\r\n\r\n public setVisibleRecursively(sceneApi: ISceneApi, args: ISceneSetVisibleArgs) {\r\n\r\n // hierarchical visibility is not set, so we fallback to what we used to do, which is setting the node and all it's children's visibility to simulate hierarchical visibility\r\n let query: clara2.IQueryObject = { name: \"*\", plug: \"Properties\", property: \"visible\" };\r\n query.includeParent = true; // include the parent in the query\r\n\r\n query.from = this.getQueryObject(sceneApi, args.objectId, args.name);\r\n if (!query.from) return;\r\n\r\n // if we're in a nested scene, then only look for nodes inside of that\r\n if (args.nestedSceneId) {\r\n (query.from as clara2.IQueryObject).from = { id: args.nestedSceneId };\r\n }\r\n\r\n let paths = sceneApi.cache.paths.getAll(query);\r\n if (paths) {\r\n paths.forEach(path => {\r\n if (!sceneApi.cache.lastValues.valueEqualTo(path, args.visible)) {\r\n sceneApi.api.scene.set(path, args.visible);\r\n Logger.logSceneChange(\"set \" + JSON.stringify(args));\r\n sceneApi.cache.lastValues.set(path, args.visible);\r\n }\r\n });\r\n }\r\n }\r\n\r\n private getQueryObjectFromArgs(sceneApi: ISceneApi, args: ISceneGetPropertyArgs): clara2.IQueryObject {\r\n return this.getQueryObject(sceneApi, args.objectId, args.name, args.plug, args.property, args.operator);\r\n }\r\n\r\n public getQueryObject(\r\n sceneApi: ISceneApi,\r\n id: string,\r\n name: string,\r\n plug?: string,\r\n property?: string,\r\n operator?: string\r\n ): clara2.IQueryObject {\r\n let o: clara2.IQueryObject = {};\r\n\r\n // temporary check for transition to V2. Old blocks will only be using objectId even if it's the name \r\n // we're after newer blocks differentiate. So we need to make sure the id is really an id. \r\n // If it isn't, then we'll use it as the name\r\n if (id) {\r\n let foundId = sceneApi.api.scene.find({ id });\r\n if (foundId) {\r\n o.id = id;\r\n } else {\r\n o.name = id;\r\n }\r\n } else if (name) {\r\n o.name = name;\r\n }\r\n if (plug) {\r\n o.plug = plug;\r\n }\r\n if (property) {\r\n o.property = property;\r\n }\r\n if (operator) {\r\n // using named operators is a little strange. We need to match the operator through it's properties. \r\n // In this case, we use the name property\r\n o.properties = { name: operator };\r\n }\r\n\r\n return o;\r\n }\r\n\r\n public animateCamera(sceneApi: ISceneApi, args: IAnimateCameraArgs) {\r\n let duration = args.duration || 3000;\r\n let easing = args.easing || \"linear\";\r\n\r\n\r\n sceneApi.cameraAnimationInProgress = true;\r\n return sceneApi.api.player.animateCameraTo(args.toCameraId, duration).then(() => {\r\n sceneApi.cameraAnimationInProgress = false;\r\n });\r\n\r\n }\r\n\r\n public animate(sceneApi: ISceneApi, args: ISceneAnimationArgs) {\r\n this.normalizePropertyValue(sceneApi, args);\r\n\r\n\r\n let query = this.getQueryObjectFromArgs(sceneApi, args);\r\n let setAll: boolean = (query.name != null); // we use setAll if this is possibly a regex query\r\n let paths = sceneApi.cache.paths.getAll(query);\r\n paths.forEach(path => {\r\n // if (!sceneApi.cache.lastValues.valueEqualTo(path, args.value)) {\r\n sceneApi.api.animation.queueAnimation({\r\n name: Utils.shortId(),\r\n iterations: args.iterations,\r\n autoplay: true,\r\n tracks: [\r\n {\r\n path: path as any,\r\n type: args.propertyType,\r\n value: args.value,\r\n duration: args.duration,\r\n easing: args.easing || \"linear\",\r\n start: args.start\r\n }\r\n ],\r\n onEnd: () => {\r\n // after the animation set the value in the cache\r\n sceneApi.cache.lastValues.set(path, args.value);\r\n }\r\n });\r\n // }\r\n });\r\n }\r\n\r\n public animateClip(sceneApi: ISceneApi, args: IAnimateClipArgs) {\r\n let clip = sceneApi.api.animation.getClips().find(c => c.name.isEqual(args.name));\r\n if (clip) {\r\n sceneApi.api.animation.queueClip(clip.id, { autoplay: true });\r\n } else {\r\n console.warn(\"Could not find animation clip with name '\" + args.name + \"'\");\r\n }\r\n }\r\n\r\n public getSceneUtilities(\r\n sceneApi: ISceneApi,\r\n ruleType: eRuleType,\r\n idMap?: {},\r\n nestedSceneId?: string) {\r\n return new ClaraSceneUtilities(this, sceneApi, ruleType, idMap, nestedSceneId);\r\n }\r\n\r\n protected runSceneRules(sceneConfig: Configurator,\r\n uiConfig: Configurator,\r\n ruleArgs: IClaraSceneRuleArgs,\r\n skipRulesIfNoNestedSceneChanges: boolean\r\n ): ng.IPromise> {\r\n return this.runNestedSceneRules(ruleArgs.sceneApi, uiConfig).then((r: any[]) => {\r\n if (!skipRulesIfNoNestedSceneChanges || (r && r.some(r2 => r2 != null))) { //skip running the rules if there were no nested scene rules run\r\n return this.importAllUploadFieldImages(ruleArgs.sceneApi, uiConfig).then(() => {\r\n ruleArgs.sceneUtils.ruleType = eRuleType.scene;\r\n return this.ruleService.runRuleTypeAsync(sceneConfig, eRuleType.scene, ruleArgs).then(ruleResult => {\r\n uiConfig.$fieldsDirtyForSceneRules = false;\r\n return ruleResult;\r\n });\r\n });\r\n }\r\n });\r\n }\r\n\r\n public runRulesCycle(\r\n sceneConfig: Configurator,\r\n uiConfig: Configurator,\r\n ruleArgs: IClaraSceneRuleArgs\r\n ): ng.IPromise> {\r\n\r\n let runUiRules = !ruleArgs.sceneApi.sceneDb[sceneConfig.idScene].idProduct;\r\n\r\n // before running the scene rules, we need to clear out transient handlers\r\n ruleArgs.sceneApi.draggableDb.clearTransient();\r\n ruleArgs.sceneApi.clickDb.clearTransient();\r\n\r\n if (runUiRules) {\r\n // run the value rule first\r\n ruleArgs.sceneUtils.ruleType = eRuleType.value;\r\n return this.ruleService.runRuleTypeAsync(sceneConfig, eRuleType.value, ruleArgs)\r\n .then(() => {\r\n sceneConfig.preValidate();\r\n sceneConfig.isValid();\r\n })\r\n .then(() => this.runSceneRules(sceneConfig, uiConfig, ruleArgs, false));\r\n } else {\r\n return this.runSceneRules(sceneConfig, uiConfig, ruleArgs, false);\r\n }\r\n }\r\n\r\n public runNestedSceneRules(\r\n sceneApi: ISceneApi,\r\n uiConfig: Configurator\r\n ) {\r\n\r\n let nestedConfigs = uiConfig.getNestedConfigurators();\r\n\r\n if (nestedConfigs.length) {\r\n let promises: ng.IPromise[] = [];\r\n // loop through nested configurators, merge the scenes if they haven't been already, and run their rules\r\n nestedConfigs.forEach(nested => {\r\n if (nested.idScene) {\r\n let refConfig = uiConfig.referencedConfigurators.find(rc => rc.idProduct == nested.idProduct);\r\n if (refConfig.nestScene) {\r\n // create the scene configurator for the nested configurator if it doesn't already exist \r\n // (or has been swapped for another scene)\r\n if (!nested.$sceneConfigurator || nested.$sceneConfigurator.idScene != nested.idScene) {\r\n nested.$sceneConfigurator = new Configurator(\r\n new KbObjectManager(),\r\n sceneApi.sceneDb[nested.idScene].configurator\r\n );\r\n nested.$fieldsDirtyForSceneRules = true;\r\n }\r\n nested.$sceneConfigurator.$uiConfigurator = nested;\r\n nested.$nestHotspots = refConfig.nestHotspots;\r\n\r\n // in case the nested scene is a standalone scene, we need to set it's fields from the uiConfig\r\n if (nested != nested.$sceneConfigurator && !nested.$sceneConfigurator.idProduct) {\r\n nested.$sceneConfigurator.setFields(nested.getFieldsObject());\r\n }\r\n\r\n let skipRules = !nested.$fieldsDirtyForSceneRules;\r\n \r\n promises.push(\r\n this.nestScene( // merge the scene if it hasn't already been merged\r\n sceneApi,\r\n sceneApi.sceneDb[nested.idScene].claraId,\r\n sceneApi.sceneDb[nested.idScene].publishHash,\r\n nested\r\n ).then(() =>\r\n // now run the rules on the nested scene\r\n this.runSceneRules(\r\n nested.$sceneConfigurator,\r\n nested,\r\n this.getNestedSceneRuleArgs(\r\n sceneApi,\r\n nested,\r\n nested.$sceneConfigurator,\r\n nested.$sceneConfigurator.$sceneIdMap,\r\n eRuleType.scene\r\n ),\r\n skipRules\r\n )\r\n )\r\n );\r\n }\r\n }\r\n });\r\n return this.$q.all(promises);\r\n } else {\r\n return (new KPromise(null)) as any;\r\n }\r\n\r\n }\r\n\r\n public getNestedSceneRuleArgs(sceneApi: ISceneApi, uiConfig: Configurator, sceneConfig: Configurator, idMap: {}, ruleType: eRuleType) {\r\n // if the scene config is standalone, then it will also act as the uiConfig for the rules\r\n if (!sceneApi.sceneDb[uiConfig.idScene].idProduct) uiConfig = uiConfig.$sceneConfigurator;\r\n let sceneUtils = this.getSceneUtilities(sceneApi, ruleType, idMap, uiConfig.$nestedSceneId);\r\n\r\n return {\r\n environment: \"\",\r\n company: {},\r\n configurator: uiConfig,\r\n kom: uiConfig.$manager,\r\n parentKom: uiConfig.$parentConfigurator ? uiConfig.$parentConfigurator.$manager : null,\r\n sceneKom: sceneConfig.$manager,\r\n sceneApi,\r\n isRender: sceneApi.isRender,\r\n isMobile: sceneApi.isMobile,\r\n clientLanguage: sceneApi.clientLanguage,\r\n logs: new ClientLogger(),\r\n upload: () => {\r\n return new KPromise(null) as any;\r\n },\r\n // TODO: leave in scene rule args for backwards compatibility. \r\n // Can be removed in the future, since it's real place is in scene utilities\r\n addModelClickHandler: args => {\r\n sceneUtils.addModelClickHandler(args);\r\n },\r\n playSceneAnimation: args => {\r\n // no need for animations server side\r\n },\r\n toggleSceneAnimation: () => {\r\n // no need for animations server side\r\n },\r\n sceneUtils,\r\n sendMessage: msg => {\r\n sceneApi.sendMessage(msg);\r\n },\r\n selectPage: page => {\r\n\r\n },\r\n convertCurrency: (obj: any) => {\r\n return null;\r\n },\r\n toggleTool: (args: IToggleToolArgs) => {\r\n\r\n },\r\n constrainCamera: (args: IConstrainCameraArgs) => {\r\n\r\n },\r\n getUploadImageNode: (args: IGetUploadImageNodeArgs) => {\r\n let a = sceneApi.importedImages[uiConfig.name + \"_\" + args.fieldId];\r\n return a ? a.imageNodeId : null;\r\n },\r\n getTables: (args: IGetTableRuleArgs) => {\r\n return sceneApi.getTables(args);\r\n }\r\n } as IClaraSceneRuleArgs;\r\n }\r\n\r\n public nodeWithIdExists(sceneApi: ISceneApi, id: string): boolean {\r\n return id && (sceneApi.api.scene.find({ id }) != null);\r\n }\r\n\r\n public nestSceneInner() {\r\n\r\n }\r\n\r\n public fetchScene(sceneApi: ISceneApi, claraId: string, publishHash: string): Q.IPromise {\r\n if (!sceneApi.fetchedScenes.hasOwnProperty(claraId)) {\r\n sceneApi.fetchedScenes[claraId] =\r\n sceneApi.api.sceneIO.fetch(claraId, publishHash, { waitForPublish: true });\r\n }\r\n return sceneApi.fetchedScenes[claraId];\r\n }\r\n\r\n protected nestScene(\r\n sceneApi: ISceneApi,\r\n claraId: string,\r\n publishHash: string,\r\n nested: Configurator\r\n ): ng.IPromise {\r\n // first check to see if this nested configurator scene has already been merged\r\n if (nested.$nestedSceneId && this.nodeWithIdExists(sceneApi, nested.$nestedSceneId)) {\r\n return (new KPromise(null)) as any;\r\n } else {\r\n let deferred = this.$q.defer();\r\n\r\n let api = sceneApi.api;\r\n let rootSceneId = api.scene.find({ includeParent: true }) as string;\r\n // first fetch the scene from the server (or cache)\r\n this.fetchScene(sceneApi, claraId, publishHash).then(() => {\r\n\r\n // if this nested scene is a child of another nested scene, \r\n // then we must place this node inside of the parent nested scene node\r\n // otherwise, just put it in the 'Objects' node of the scene\r\n let parentId: string;\r\n if (nested.$parentConfigurator && nested.$parentConfigurator.$nestedSceneId) {\r\n parentId = nested.$parentConfigurator.$nestedSceneId;\r\n } else {\r\n parentId = sceneApi.cache.paths.getId({ type: \"Objects\" }) as string; // get the 'Objects' node id\r\n }\r\n\r\n // now that we've fetched the nested scene template, we need to add a null node to house it\r\n api.sceneGraph.addNode({\r\n name: this.NESTED_SCENE_PREFIX + nested.name,\r\n parent: parentId,\r\n type: \"Null\",\r\n plugs: {\r\n Transform: [[\"Transform\", {}]],\r\n Properties: [[\"Default\", {}]]\r\n }\r\n }).then(nullId => {\r\n // we have our new null node to house the nested scene. \r\n // Now we need to copy nodes from the other scene into it\r\n let nestedObjectsNodeId = sceneApi.cache.paths.getId({\r\n from: { id: claraId },\r\n name: \"Objects\"\r\n }) as string;\r\n let nestedMaterialsNodeId = sceneApi.cache.paths.getId({\r\n from: { id: claraId },\r\n name: \"Material Library\"\r\n }) as string;\r\n let parentMaterialsNodeId = sceneApi.cache.paths.getId({\r\n from: { id: rootSceneId },\r\n name: \"Material Library\"\r\n }) as string;\r\n\r\n // only clone nodes that make sense - materials can stay where they're \r\n // at and still be used.Ignore cameras, lights, etc.\r\n let objectsToClone = api.scene.filter({\r\n from: { id: nestedObjectsNodeId },\r\n type: [\"PolyMesh\", \"BinMesh\", \"Null\", \"Model\", \"Annotation\", \"Helper\"]\r\n }) as string[];\r\n let materialsToClone = api.scene.filter({\r\n from: { id: nestedMaterialsNodeId },\r\n type: [\"Material\"]\r\n }) as string[];\r\n let allNodesToClone = objectsToClone.concat(materialsToClone);\r\n\r\n // create a parent map to tell the cloned nodes where to go\r\n let parentMap = {};\r\n // nested object nodes to go into our new null\r\n parentMap[nestedObjectsNodeId] = nullId;\r\n // nested material nodes to go into the parent material library\r\n parentMap[nestedMaterialsNodeId] = parentMaterialsNodeId;\r\n\r\n // this.dumpScene(sceneApi, api.scene.find({ includeParent: true }), 0);\r\n api.sceneGraph.clone(allNodesToClone, parentMap, { cloneDependencies: true }).then(nodeMap => {\r\n // console.log('new nodes', nodeMap);\r\n let sceneId = api.scene.find({ includeParent: true }) as string;\r\n // this.dumpScene(sceneApi, sceneId, 0);\r\n // this.checkScene(sceneApi, sceneId, 0, sceneId);\r\n \r\n // store the node map into the scene configurator\r\n nested.$sceneConfigurator.$sceneIdMap = nodeMap;\r\n // set the nested scene id of the configurator to make it easier to find this node by id\r\n nested.$nestedSceneId = nullId;\r\n\r\n if (sceneApi.onSceneNested) {\r\n sceneApi.onSceneNested(nested, nullId);\r\n }\r\n\r\n let nestedRuleArgs = this.getNestedSceneRuleArgs(\r\n sceneApi,\r\n nested,\r\n nested.$sceneConfigurator,\r\n nested.$sceneConfigurator.$sceneIdMap,\r\n eRuleType.sceneLoaded\r\n );\r\n this.ruleService.runRuleTypeAsync(nested.$sceneConfigurator, eRuleType.sceneLoaded, nestedRuleArgs).then(() => {\r\n deferred.resolve();\r\n });\r\n });\r\n });\r\n });\r\n return deferred.promise;\r\n }\r\n }\r\n\r\n public deleteOrphanedNestedScenes(sceneApi: ISceneApi, uiConfig: Configurator) {\r\n let allNested = uiConfig.getAllConfigurators();\r\n\r\n let api = sceneApi.api;\r\n let nestedSceneIds = api.scene.filter({ name: this.NESTED_SCENE_PREFIX + \"*\" }) as string[];\r\n nestedSceneIds.forEach(id => {\r\n if (!allNested.some(c => c.$nestedSceneId == id)) {\r\n api.sceneGraph.deleteNode(id);\r\n }\r\n });\r\n\r\n }\r\n\r\n /**\r\n * used to output the heirarchy for debugging\r\n * @param level\r\n */\r\n public dumpScene(sceneApi: ISceneApi, nodeId: string, level: number) {\r\n let api = sceneApi.api;\r\n if (nodeId == null) {\r\n nodeId = sceneApi.api.scene.find({ includeParent: true }) as string;\r\n level = 0;\r\n }\r\n // tslint:disable-next-line:no-console\r\n console.log(new Array(level + 1).join(\" \"), \" - \", api.scene.get({ id: nodeId, property: \"name\" }), \" - \", nodeId);\r\n let paths = api.scene.filter({ from: { id: nodeId }, shallow: true }) as string[];\r\n paths.forEach(id => this.dumpScene(sceneApi, id, level + 1));\r\n }\r\n\r\n public checkScene(sceneApi: ISceneApi, nodeId: string, level, parentId) {\r\n let api = sceneApi.api;\r\n let name = api.scene.get({ id: nodeId, property: \"name\" });\r\n if (!name) {\r\n console.error(\r\n \"No data for child: \", nodeId, \"child of: \", api.scene.get({ id: parentId, property: \"name\" })\r\n );\r\n }\r\n let children = api._store.getIn([\"sceneGraph\", nodeId, \"children\"]);\r\n children.forEach(id => this.checkScene(sceneApi, id, level + 1, nodeId));\r\n }\r\n\r\n public importAllUploadFieldImages(sceneApi: ISceneApi, uiConfig: Configurator): ng.IPromise {\r\n let promise = new KPromise(null) as any;\r\n\r\n // only find fields with an assetId but don't have an image node yet. \r\n // The asset should have already been imported at time of upload\r\n // (has to be this way because we don't have the File object)\r\n let uploadFields = uiConfig.getFields(f =>\r\n f.type == eFieldType.upload &&\r\n f.uploadToScene\r\n );\r\n if (uploadFields.length) {\r\n let promises: ng.IPromise[] = [];\r\n uploadFields.forEach(uf => {\r\n promises.push(this.importUploadFieldImage(sceneApi, uiConfig, uf));\r\n });\r\n promise = this.$q.all(promises);\r\n }\r\n\r\n return promise;\r\n }\r\n\r\n public importUploadFieldImage(sceneApi: ISceneApi, uiConfig: Configurator, field: Field, file?: File): ng.IPromise {\r\n let promise = new KPromise(null) as PromiseLike;\r\n let uploadValue = field.value as IUploadValue;\r\n let api = sceneApi.api;\r\n let isRender = sceneApi.isRender;\r\n\r\n // only import if the upload field is set to upload to scene\r\n if (field.uploadToScene) { \r\n let prefix = uiConfig.isNested() ? uiConfig.name : \"\";\r\n prefix += \"_\" + field.name;\r\n let nullNodeName = prefix + \"_null\";\r\n let imageNodeName = prefix + \"_image\";\r\n let shapeNodeName = prefix + \"_shape\";\r\n let extrudeNodeName = prefix + \"_extrude\";\r\n let options: clara2.IImageImportOptions = {outputName: imageNodeName};\r\n\r\n if (field.convertUploadedSceneImageToMesh) {\r\n options = {\r\n targetFormat: \"svg\",\r\n mode: \"threshold\",\r\n threshold: field.uploadImageThreshold,\r\n backgroundColor: \"#00FFFFFF\",\r\n outputName: imageNodeName\r\n };\r\n }\r\n\r\n // if there is already an asset id, and it has an image node, then there is nothing to do here\r\n // if there is no asset id, then this file still needs to get uploaded to assets\r\n let importObject = null;\r\n let prevImportedImage = sceneApi.importedImages[uiConfig.name + \"_\" + field.id];\r\n\r\n if (file && !uploadValue.assetId) { //user just uploaded \r\n importObject = file;\r\n } else if (uploadValue.assetId && !prevImportedImage) { //uploaded this session (and not an svg conversion)\r\n // pass the assetId to import to make the image node\r\n importObject = uploadValue.assetId;\r\n }\r\n\r\n if (importObject) {\r\n promise = sceneApi.api.assets.importImage(importObject, options);\r\n } else {\r\n return promise as any;\r\n }\r\n\r\n //clean up old svg image if it exists\r\n let svgNodeId = api.scene.find(imageNodeName + \".svg\") as string;\r\n if (svgNodeId) {\r\n api.sceneGraph.deleteNode(svgNodeId);\r\n }\r\n promise.then(r => {\r\n uploadValue.assetId = r.assetId;\r\n sceneApi.importedImages[uiConfig.name + \"_\" + field.id] = { imageNodeId: r.imageNodeId, threshold: field.uploadImageThreshold };\r\n \r\n if (field.convertUploadedSceneImageToMesh) {\r\n //create a null to house the shape if one doesn't already exist\r\n let nullNodeId = api.scene.find(nullNodeName) as string;\r\n if (!nullNodeId) {\r\n api.scene.addNode({\r\n name: nullNodeName,\r\n parent: api.scene.find('Objects') as string,\r\n type: \"Null\",\r\n plugs: {\r\n Transform: [[\"Transform\", {}]],\r\n Properties: [[\"Default\", {}]]\r\n }\r\n });\r\n nullNodeId = api.scene.find(nullNodeName) as string;\r\n }\r\n\r\n //if the shape node already exists, then delete it\r\n //if it doesn't exist, then create it\r\n let shapeNodeId = api.scene.find(shapeNodeName) as string;\r\n if (shapeNodeId) {\r\n api.sceneGraph.deleteNode(shapeNodeId);\r\n sceneApi.cache.paths.clearEntriesThatContain(shapeNodeName, shapeNodeId);\r\n }\r\n api.scene.addNode({\r\n name: shapeNodeName,\r\n type: 'Shape',\r\n parent: nullNodeId,\r\n plugs: {\r\n Shape: [\r\n [\r\n 'SVGShape',\r\n {\r\n image: r.imageNodeId,\r\n curveSegments: 8,\r\n },\r\n ],\r\n ]\r\n },\r\n });\r\n \r\n shapeNodeId = api.scene.find(shapeNodeName) as string;\r\n\r\n // Resize shape (default operation is to fit a 1x1 square)\r\n api.scene.addOperator(\r\n shapeNodeId,\r\n 'Shape',\r\n 'ResizeShape',\r\n { keepAspectRatio: true }\r\n );\r\n\r\n // Center the shape since center of svg is on top left corner\r\n api.scene.addOperator(\r\n shapeNodeId,\r\n 'Shape',\r\n 'CenterShape',\r\n {}\r\n );\r\n\r\n //add an extrude of the shape\r\n let extrudeNodeId = api.scene.find(extrudeNodeName) as string;\r\n if (extrudeNodeId) {\r\n api.sceneGraph.deleteNode(extrudeNodeId);\r\n sceneApi.cache.paths.clearEntriesThatContain(extrudeNodeName, extrudeNodeId);\r\n }\r\n api.scene.addNode({\r\n name: extrudeNodeName,\r\n type: \"PolyMesh\",\r\n parent: nullNodeId,\r\n plugs: {\r\n PolyMesh: [\r\n [\r\n \"FromShapeWithExtrude\",\r\n {\r\n shape: shapeNodeId,\r\n extrudeLength: 0.1\r\n }\r\n ]\r\n ]\r\n }\r\n });\r\n }\r\n });\r\n }\r\n return promise as ng.IPromise;\r\n }\r\n\r\n public snapshot(sceneApi: ISceneApi, options: clara2.ISnapshotOptions): Blob | string {\r\n sceneApi.api.commands.setCommandOptions('snapshot', options);\r\n var result = sceneApi.api.commands.runCommand('snapshot');\r\n return result;\r\n }\r\n\r\n public getRootSceneId(sceneApi?: ISceneApi) {\r\n return sceneApi.api.scene.find({ includeParent: true }) as string;\r\n }\r\n\r\n public frameScene(sceneApi: ISceneApi, args?: IFrameSceneArgs) {\r\n var nodeList = args ? [args.node] : null;\r\n sceneApi.api.player.frameScene(nodeList, args);\r\n }\r\n\r\n public isHierarchicalVisibilityEnabled(sceneApi: ISceneApi): boolean {\r\n let rootSceneId = sceneApi.api.scene.find({ includeParent: true }) as string;\r\n let r = sceneApi.api.scene.get({\r\n id: rootSceneId,\r\n plug: \"Properties\",\r\n property: \"hierarchyVisibility\"\r\n }) as string;\r\n return r == \"Enable\";\r\n }\r\n\r\n public ghost(sceneApi: ISceneApi, args: IGhostArgs) {\r\n if (!sceneApi.ghoster) {\r\n sceneApi.ghoster = sceneApi.api.selection.addGhoster({ opacity: .7 });\r\n }\r\n let nodeIds = sceneApi.api.scene.filter({ from: { id: args.id }, includeParent: true }) as string[];\r\n nodeIds.forEach(n => {\r\n if (args.on) {\r\n sceneApi.ghoster.selectionSet.add(n);\r\n } else {\r\n sceneApi.ghoster.selectionSet.remove(n);\r\n }\r\n });\r\n }\r\n\r\n public highlight(sceneApi: ISceneApi, args: IHighlightArgs, type: eHighlightType) {\r\n if (!sceneApi.highlighter) {\r\n sceneApi.highlighter = sceneApi.api.selection.setHighlighting(true, { color: \"#ff0000\", thickness: 2 });\r\n }\r\n\r\n let nodeIds = sceneApi.api.scene.filter({ from: { id: args.id }, includeParent: true, type: [\"PolyMesh\", \"BinMesh\", /*\"Null\",*/ \"Model\", \"Annotation\", \"Helper\"] }) as string[];\r\n let highlighter = sceneApi.highlighter;\r\n nodeIds.forEach(n => {\r\n if (args.on) {\r\n highlighter.selectionSet.add(n);\r\n sceneApi.highlights[type][n] = true;\r\n } else {\r\n highlighter.selectionSet.remove(n);\r\n delete sceneApi.highlights[type][n];\r\n }\r\n });\r\n }\r\n\r\n public clearHighlightsOfType(sceneApi: ISceneApi, type: eHighlightType) {\r\n let types = [eHighlightType.user, eHighlightType.selection, eHighlightType.hover];\r\n types.remove(type);\r\n for (let id in sceneApi.highlights[type]) {\r\n //only remove if the node is not part of another highlight type\r\n let shouldUnhighlight = !types.some(t => sceneApi.highlights[t][id]);\r\n\r\n if (shouldUnhighlight && sceneApi.highlighter) {\r\n sceneApi.highlighter.selectionSet.remove(id);\r\n }\r\n }\r\n sceneApi.highlights[type] = {};\r\n }\r\n\r\n public clearGhosts(sceneApi: ISceneApi) {\r\n if (sceneApi.ghoster) {\r\n sceneApi.ghoster.selectionSet.clear();\r\n }\r\n }\r\n\r\n public select(sceneApi: ISceneApi, args: ISelectNodeArgs) {\r\n if (!sceneApi.selector) {\r\n sceneApi.selector = sceneApi.api.selection.createSelectionSet();\r\n sceneApi.api.selection.setActiveSelectionSet(sceneApi.selector);\r\n }\r\n if (!sceneApi.selectedNodes.contains(args.id)) {\r\n this.clearSelection(sceneApi);\r\n\r\n sceneApi.selectedNodes.push(args.id);\r\n sceneApi.selector.add(args.id);\r\n\r\n this.highlight(sceneApi, { id: args.id, on: true }, eHighlightType.selection);\r\n }\r\n }\r\n\r\n public deselect(sceneApi: ISceneApi, nodeId: string) {\r\n this.highlight(sceneApi, { id: nodeId, on: false }, eHighlightType.selection);\r\n sceneApi.selectedNodes.remove(nodeId);\r\n sceneApi.selector && sceneApi.selector.remove(nodeId);\r\n }\r\n\r\n public clearSelection(sceneApi: ISceneApi) {\r\n for (let i = sceneApi.selectedNodes.length - 1; i >= 0; i--) {\r\n this.deselect(sceneApi, sceneApi.selectedNodes[i]);\r\n }\r\n }\r\n\r\n public getThree(sceneApi: ISceneApi): any {\r\n return sceneApi.api.player.getThree().THREE;\r\n }\r\n}\r\n","import { DI } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs, eBundle } from \"@app/helpers/dirs\";\r\nimport { AuthService } from \"@app/services/auth.service\";\r\nimport { eViewType } from \"@models\";\r\nimport { StateProvider } from \"@uirouter/angularjs\";\r\nimport * as angular from \"angular\";\r\n\r\nexport class StateHelper {\r\n constructor(\r\n private $stateProvider: StateProvider,\r\n private bundle: eBundle\r\n ) {\r\n \r\n }\r\n public getPluralName(name: string) {\r\n let plural = name;\r\n if (!name.endsWith(\"s\")) {\r\n if (name.endsWith(\"y\")) {\r\n plural = name.slice(0, -1) + \"ies\";\r\n } else {\r\n plural = name + \"s\";\r\n }\r\n }\r\n return plural;\r\n }\r\n\r\n public addState(o: {\r\n name: string,\r\n view?: Token,\r\n url?: string,\r\n params?: {},\r\n data?: any,\r\n allowAnonymous?: boolean,\r\n reloadOnSearch?: boolean,\r\n abstract?: boolean,\r\n templateName?: string,\r\n templateUrl?: string,\r\n template?: string,\r\n parent?: string\r\n }) {\r\n let ngInject = o.view && DI.get(o.view);\r\n let resolve = ngInject && Object.assign({}, ngInject.resolveObject);\r\n let nameSegment = o.name.split(\".\").last();\r\n let kebab = nameSegment.toKebabCase();\r\n if (!o.allowAnonymous && resolve) {\r\n resolve[\"auth\"] = [\r\n Token.AuthService.key,\r\n (authService: AuthService) => {\r\n return authService.authPromise;\r\n }\r\n ];\r\n }\r\n else if (o.allowAnonymous) {\r\n if (!o.data) o.data = {};\r\n o.data.allowAnonymous = true;\r\n }\r\n\r\n this.$stateProvider.state(o.name, {\r\n url: angular.isDefined(o.url) ? o.url : `/${kebab}`,\r\n params: o.params,\r\n template: () => { return o.template || Dirs.get(o.templateUrl) || Dirs.view(o.templateName || kebab, this.bundle) },\r\n // templateUrl: o.templateUrl || Dirs.view(o.templateName || kebab, this.bundle),\r\n controller: ngInject && ngInject.construct,\r\n resolve: resolve,\r\n data: o.data,\r\n reloadOnSearch: o.reloadOnSearch,\r\n parent: o.parent\r\n });\r\n }\r\n\r\n public addSearchState(o: {\r\n name: string,\r\n view: Token,\r\n url?: string\r\n }) {\r\n let nameSegment = o.name.split(\".\").last();\r\n this.addState({\r\n name: o.name,\r\n view: o.view,\r\n url: o.url? o.url: `/${nameSegment.toKebabCase()}?search&searchid`,\r\n params: {\r\n search: { dynamic: true },\r\n searchid: { dynamic: true }\r\n }\r\n });\r\n }\r\n\r\n public addCrudStates(o: {\r\n name: string,\r\n view: Token,\r\n searchView: Token,\r\n isSnapBased?: boolean,\r\n templateUrl?: string,\r\n template?: string,\r\n // Lists possible state params that can be applied to a new entity. For instance,\r\n // quote outputs may initialize with an output type state param\r\n newStateParams?:string[]\r\n }) {\r\n\r\n let nameSegment = o.name.split(\".\").last();\r\n let nameKebab = nameSegment.toKebabCase();\r\n let pluralName = this.getPluralName(nameSegment);\r\n let baseUrl = `/${pluralName.toKebabCase()}`;\r\n let statePrefix = o.name.substring(0, o.name.lastIndexOf(\".\"));\r\n let editStatePrefix = `${statePrefix}${o.isSnapBased ? \".base\" : \"\"}`;\r\n\r\n this.addSearchState({ // the 'search' view\r\n name: `${statePrefix}.${pluralName}`,\r\n view: o.searchView\r\n });\r\n let newStateConfig = { // the 'new' view\r\n name: `${editStatePrefix}.${nameSegment}New`,\r\n url: `${baseUrl}/new`,\r\n templateName: nameKebab,\r\n templateUrl: o.templateUrl,\r\n template: o.template,\r\n view: o.view,\r\n data: { viewType: eViewType.new }\r\n };\r\n if (o.newStateParams) newStateConfig.url += \"/:\" + o.newStateParams.join(\"/:\")\r\n this.addState(newStateConfig);\r\n this.addState({ // the 'edit' view\r\n name: `${editStatePrefix}.${nameSegment}Edit`,\r\n url: `${baseUrl}/:id${o.isSnapBased ? \"?sel\" : \"\"}`,\r\n templateName: nameKebab,\r\n templateUrl: o.templateUrl,\r\n template: o.template,\r\n view: o.view,\r\n data: { viewType: eViewType.edit },\r\n reloadOnSearch: !o.isSnapBased\r\n });\r\n }\r\n}\r\n","import { NgAnimation } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\n@NgAnimation({\r\n token: Token.KbRise,\r\n dependencies: [\r\n Token.$Timeout\r\n ]\r\n})\r\nexport class KbRise implements ng.animate.IAnimateCallbackObject {\r\n constructor(\r\n private $timeout: ng.ITimeoutService\r\n ) {\r\n\r\n let duration = (distance: number) => {\r\n return Math.max(Math.min(distance / 2, 350), 150);\r\n };\r\n\r\n let show = (element: JQuery, done) => {\r\n let origOpacity = element.css(\"opacity\");\r\n let origOverflow = element.css(\"overflow\");\r\n element.css(\"opacity\", 0);\r\n element.removeClass(\"ng-hide\");\r\n let finalSetHeight = element.hasClass(\"kb-rise--full-height\") ? element.css(\"max-height\") : \"auto\";\r\n element.css(\"height\", finalSetHeight);\r\n let autoHeight: any = element.height();\r\n if (!autoHeight) autoHeight = \"95%\";\r\n element.height(0);\r\n element.css(\"opacity\", origOpacity);\r\n element.animate({ height: autoHeight }, duration(autoHeight), () => {\r\n element.css(\"height\", finalSetHeight);\r\n done();\r\n });\r\n };\r\n\r\n let hide = (element, done) => {\r\n this.autoHeight = element.height();\r\n\r\n element.animate({ height: 0 }, duration(this.autoHeight), () => {\r\n element.css(\"height\", 0);\r\n done();\r\n });\r\n };\r\n\r\n this.beforeAddClass = (element, className, done) => {\r\n if (className == \"ng-hide\") {\r\n hide(element, done);\r\n }\r\n };\r\n this.removeClass = (element, className, done) => {\r\n if (className == \"ng-hide\") {\r\n show(element, done);\r\n }\r\n };\r\n this.enter = (element, done) => {\r\n show(element, done);\r\n };\r\n this.leave = (element, done) => {\r\n hide(element, done);\r\n };\r\n }\r\n\r\n private autoHeight: number;\r\n public beforeAddClass: (element, className, done) => void;\r\n public removeClass: (element, className, done) => void;\r\n public enter: (element, done) => void;\r\n public leave: (element, done) => void;\r\n}\r\n\r\n// export class kbSlide extends ngAnimation {\r\n// public injection(): any[] {\r\n// return [\r\n// Token.$Timeout,\r\n// ($timeout) => { return new kbSlide($timeout) }\r\n// ]\r\n// }\r\n\r\n// constructor($timeout: ng.ITimeoutService) {\r\n// super();\r\n\r\n// var show = (element: ng.IAugmentedJQuery , done) => {\r\n// element.removeClass(\"ng-hide\");\r\n// element.css(\"width\", \"auto\");\r\n// var autoWidth: any = element.width();\r\n// if (!autoWidth) autoWidth = \"95%\";\r\n// element.width(0);\r\n// element.animate({ \"width\": autoWidth }, 150, \"linear\", () => {\r\n// element.css(\"width\", \"auto\");\r\n// done();\r\n// });\r\n// }\r\n\r\n// var hide = (element: ng.IAugmentedJQuery, done) => {\r\n// this.autoWidth = element.width();\r\n\r\n// element.animate({ \"width\": 0 }, 150, () => {\r\n// element.css(\"width\", 0);\r\n// done();\r\n// });\r\n// }\r\n\r\n// this.beforeAddClass = (element: ng.IAugmentedJQuery, className: string, done) => {\r\n// if (className == \"ng-hide\") {\r\n// hide(element, done);\r\n// }\r\n// }\r\n\r\n// this.removeClass = (element: ng.IAugmentedJQuery, className: string, done) => {\r\n// if (className == \"ng-hide\") {\r\n// show(element, done);\r\n// }\r\n// }\r\n\r\n// }\r\n\r\n// private autoWidth: number;\r\n// }\r\n\r\n// export class kbFade extends ngAnimation {\r\n// public injection(): any[] {\r\n// return [\r\n// () => { return new kbFade() }\r\n// ]\r\n// }\r\n\r\n// constructor() {\r\n// super();\r\n\r\n// this.addClass = (element, className, done) => {\r\n// if (className == \"ng-hide\") {\r\n// var origOpacity = element.css(\"opacity\");\r\n\r\n// element.animate({ \"opacity\": 0 }, 150, () => {\r\n// element.hide();\r\n// element.css(\"opacity\", origOpacity);\r\n// done();\r\n// });\r\n// }\r\n// }\r\n// this.removeClass = (element, className, done) => {\r\n// if (className == \"ng-hide\") {\r\n// var origOpacity = element.css(\"opacity\");\r\n// element.css(\"opacity\", 0);\r\n// element.show();\r\n\r\n// var to = \"1\";\r\n// if (origOpacity && origOpacity != \"0\") {\r\n// to = origOpacity;\r\n// }\r\n\r\n// element.animate({ \"opacity\": to }, 150, () => {\r\n// element.show();\r\n// element.css(\"opacity\", to);\r\n// done();\r\n// });\r\n// }\r\n// }\r\n\r\n// }\r\n// }\r\n","\r\nexport class Directive implements ng.IDirective {\r\n public priority: number;\r\n public template: string;\r\n public templateUrl: string;\r\n public replace: boolean;\r\n public transclude: any;\r\n public restrict: string;\r\n public scope: any;\r\n public link: (\r\n scope: ng.IScope,\r\n instanceElement: ng.IAugmentedJQuery,\r\n instanceAttributes: ng.IAttributes,\r\n controller: any,\r\n transclude: ng.ITranscludeFunction\r\n ) => void;\r\n public compile: (\r\n templateElement: ng.IAugmentedJQuery,\r\n templateAttributes: ng.IAttributes,\r\n transclude: ng.ITranscludeFunction\r\n ) => any;\r\n public controller: any;\r\n public require: any;\r\n public terminal: boolean;\r\n public $$tlb: boolean;\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\n\r\ninterface IActionSelectScope extends ng.IScope {\r\n source: any;\r\n defaultLabel: string;\r\n onAction: (value: string) => {};\r\n _actionSelect: any;\r\n}\r\n\r\n@NgComponent({\r\n token: Token.KbActionSelect,\r\n dependencies: [\r\n Token.$Q,\r\n Token.$Http,\r\n ]\r\n})\r\nexport class KbActionSelect extends Directive {\r\n\r\n constructor(\r\n $q: ng.IQService,\r\n $http: ng.IHttpService\r\n ) {\r\n\r\n super();\r\n\r\n this.restrict = \"EA\";\r\n this.template = Dirs.component(\"kb-action-select\");\r\n this.scope = {\r\n source: \"=\",\r\n valueField: \"@\",\r\n defaultLabel: \"@\",\r\n icon: \"@\",\r\n onAction: \"=\"\r\n };\r\n this.replace = true;\r\n\r\n this.link = (scope: IActionSelectScope, element: JQuery, atts, ngModel: ng.INgModelController) => {\r\n scope._actionSelect = \"\";\r\n\r\n scope.$watch(\"_actionSelect\", (newValue: string) => {\r\n if (!newValue) return;\r\n scope.onAction(newValue);\r\n scope._actionSelect = \"\";\r\n });\r\n };\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\n@NgComponent({\r\n token: Token.KbAllowFraction,\r\n dependencies: [\r\n Token.$Q,\r\n Token.$Http,\r\n ]\r\n})\r\nexport class KbAllowFractions extends Directive {\r\n constructor() {\r\n super();\r\n this.restrict = \"A\";\r\n this.require = \"ngModel\";\r\n \r\n this.link = (scope, elem, attr, ctrl) => {\r\n let maxValidator = value => {\r\n let allowFractions = scope.$eval(attr.kbAllowFractions) || true;\r\n if (!allowFractions && value % 1 != 0) {\r\n let newValue = Math.round(value);\r\n $(elem).val(newValue);\r\n return newValue;\r\n }\r\n return value;\r\n };\r\n\r\n ctrl.$parsers.push(maxValidator);\r\n ctrl.$formatters.push(maxValidator);\r\n };\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { Utils } from \"@tools\";\r\n\r\ninterface IAtomScope extends ng.IScope {\r\n _editing: boolean;\r\n _displayClick: (event: ng.IAngularEvent) => void;\r\n _editClick: (event: ng.IAngularEvent) => void;\r\n _editMode: boolean;\r\n}\r\n\r\n@NgComponent({\r\n token: Token.KbAtom,\r\n dependencies: [\r\n Token.$Timeout\r\n ]\r\n})\r\nexport class KbAtom extends Directive {\r\n \r\n constructor($timeout: ng.ITimeoutService) {\r\n super();\r\n\r\n this.restrict = \"E\";\r\n this.template = Dirs.component(\"kb-atom\");\r\n this.scope = false;\r\n this.replace = true;\r\n this.transclude = {\r\n display: \"?kbAtomDisplay\",\r\n edit: \"?kbAtomEdit\"\r\n };\r\n\r\n this.link = (scope: IAtomScope, element: ng.IAugmentedJQuery, atts: ng.IAttributes) => {\r\n scope._editMode = scope.$eval(atts.editMode) == true;\r\n\r\n let guid = Utils.shortId();\r\n let eventName = \"click.kbAtom.\" + guid;\r\n\r\n let documentClick = (e: JQueryEventObject) => {\r\n // ignore if it was this kbAtom that was clicked\r\n if (!$(e.target).is(element) && !$.contains(element[0], e.target as Element)) {\r\n scope.$apply(() => {\r\n scope._editing = false;\r\n });\r\n $(document).off(eventName, documentClick);\r\n }\r\n };\r\n\r\n let changeEditMode = (val: boolean) => {\r\n scope._editing = val;\r\n if (val) {\r\n scope._displayClick = ($event: ng.IAngularEvent) => {\r\n };\r\n // scope._editClick = ($event: ng.IAngularEvent) => {\r\n // }\r\n } else {\r\n scope._displayClick = ($event: ng.IAngularEvent) => {\r\n if ($(element).hasClass(\"disabled\") || $(element).attr(\"disabled\")) return;\r\n // $event.stopPropagation();\r\n\r\n scope._editing = true;\r\n\r\n $(document).on(eventName, documentClick);\r\n };\r\n\r\n // scope._editClick = ($event: ng.IAngularEvent) => {\r\n // $event.stopPropagation();\r\n // }\r\n }\r\n };\r\n \r\n let editAtt = atts.editMode;\r\n if (editAtt) {\r\n scope.$watch(() => scope.$eval(editAtt), changeEditMode);\r\n } else {\r\n changeEditMode(false);\r\n }\r\n\r\n scope.$on(\"$destroy\", () => {\r\n $(document).off(eventName, documentClick);\r\n });\r\n \r\n };\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { DialogService } from \"@app/services/dialog.service\";\r\nimport { StorageService } from \"@app/services/storage.service\";\r\nimport { UploadService } from \"@app/services/upload.service\";\r\nimport { DialogButton, eFileSource, eFileStatus, eInputDialogType, IKbFile, IQuoteFile, IRootScope, MediaDialogButton } from \"@models\";\r\nimport { icons } from \"@tools\";\r\n\r\n@NgComponent({\r\n token: Token.KbAttachments,\r\n dependencies: [\r\n Token.$RootScope,\r\n Token.DialogService,\r\n Token.$Http,\r\n Token.$Q,\r\n Token.UploadService,\r\n Token.StorageService\r\n ]\r\n})\r\nexport class KbAttachments extends Directive {\r\n\r\n constructor(\r\n private $rootScope: IRootScope,\r\n private dialogService: DialogService,\r\n private $http: ng.IHttpService,\r\n private $q: ng.IQService,\r\n private uploadService: UploadService,\r\n private storageService: StorageService\r\n ) {\r\n super();\r\n\r\n this.replace = false;\r\n this.template = Dirs.component(\"kb-attachments\");\r\n this.restrict = \"E\";\r\n this.scope = {\r\n objectId: \"=\",\r\n tableName: \"@\",\r\n relationshipProperty: \"@\",\r\n files: \"=\",\r\n fileEntityPath: \"@\",\r\n canChange: \"=\",\r\n canAdd: \"=\",\r\n downloadFile: \"=\"\r\n };\r\n\r\n this.link = (scope: any, element, atts: any) => {\r\n if (typeof scope.canChange == \"undefined\") {\r\n scope.canChange = $rootScope.user.canModifyAllAttachments || $rootScope.user.canAddAttachments;\r\n }\r\n if (typeof scope.secureFileDownloadUrl == \"undefined\") scope.secureFileDownloadUrl = \"file/download\";\r\n\r\n let displayDialog = (callback, file?, name: string = \"\", description: string = \"\", source?) => {\r\n let fileInfo = scope.$new(true);\r\n if (!file) file = { name: \"\" };\r\n let mediaButton = \"\";\r\n\r\n fileInfo.model = {\r\n fileName: file.name,\r\n name,\r\n description,\r\n source\r\n };\r\n\r\n fileInfo.canViewMedia = this.$rootScope.context.user.canModifyMedia;\r\n\r\n dialogService.dialog({\r\n type: eInputDialogType.html,\r\n template: Dirs.view(\"dialog-edit-attachment\"),\r\n scope: fileInfo,\r\n buttons: [\r\n new DialogButton(loc.ok, icons.submit, () => {\r\n callback(fileInfo.model.name, fileInfo.model.description, file, fileInfo.model.source);\r\n }),\r\n new DialogButton(loc.cancel, icons.cancel)]\r\n });\r\n\r\n fileInfo.uploadNewAttachment = () => {\r\n this.uploadService.promptUserToChooseFile(atts.accept).then(selectedFile => {\r\n if (file.name == fileInfo.model.name || !fileInfo.model.name) {\r\n fileInfo.model.name = selectedFile.name;\r\n }\r\n fileInfo.model.fileName = selectedFile.name;\r\n fileInfo.model.source = eFileSource.uploaded;\r\n file = selectedFile;\r\n });\r\n };\r\n\r\n fileInfo.selectMediaFile = () => {\r\n let name = fileInfo.model.name;\r\n let description = fileInfo.model.description;\r\n dialogService.mediaSelect({\r\n buttons: [\r\n new MediaDialogButton(loc.ok, icons.success, args => {\r\n if (!name || name == file.name) {\r\n fileInfo.model.name = args.selectedItem.name;\r\n }\r\n fileInfo.model.fileName = args.selectedItem.name;\r\n fileInfo.model.source = eFileSource.media;\r\n file = args.selectedItem;\r\n }),\r\n new MediaDialogButton(loc.cancel, icons.cancel, args => {\r\n\r\n })\r\n ]\r\n });\r\n };\r\n };\r\n\r\n if (!scope.downloadFile) {\r\n scope.downloadFile = item => {\r\n if (typeof window != \"undefined\") {\r\n window.open(storageService.getMediaUrl(item.filePath));\r\n }\r\n };\r\n }\r\n\r\n scope._uploadFile = (item?: IQuoteFile) => {\r\n if (!item) { item = {\r\n filePath: \"\",\r\n name: \"\",\r\n description: \"\",\r\n source: null\r\n };\r\n }\r\n displayDialog((name, description, file, source) => {\r\n let promise;\r\n let newFileEntity: IKbFile = {\r\n name,\r\n description,\r\n id: item.id,\r\n filePath: file.name,\r\n // idCompany: $rootScope.company.id,\r\n // idUser: $rootScope.user.id,\r\n createdBy: $rootScope.user.id,\r\n // tableName: scope.tableName,\r\n createdByName: $rootScope.user.firstName + \" \" + $rootScope.user.lastName,\r\n source: null,\r\n status: eFileStatus.complete\r\n };\r\n if (source) newFileEntity.source = source;\r\n if (newFileEntity.source == eFileSource.media) newFileEntity.filePath = file.name;\r\n if (scope.objectId && scope.relationshipProperty) {\r\n newFileEntity[scope.relationshipProperty] = scope.objectId;\r\n }\r\n if (file && source != eFileSource.media) {\r\n let url = scope.postUrl;\r\n let deferred = $q.defer();\r\n dialogService.alert({\r\n promise: deferred.promise,\r\n successMsg: \"Upload complete\"\r\n });\r\n\r\n let uploadProgress = evt => {\r\n if (evt.lengthComputable) {\r\n deferred.notify(Math.round(evt.loaded * 100 / evt.total));\r\n } else {\r\n deferred.notify(\"Unknown File Size\");\r\n }\r\n };\r\n\r\n let uploadComplete = (result) => {\r\n deferred.resolve();\r\n if (item.id) {\r\n $.extend(item, newFileEntity);\r\n } else {\r\n newFileEntity.id = result.id;\r\n scope.files.push(newFileEntity);\r\n }\r\n };\r\n\r\n let uploadFailed = () => {\r\n deferred.reject(\"Upload failed\");\r\n };\r\n\r\n let uploadCanceled = () => {\r\n deferred.reject();\r\n };\r\n\r\n this.uploadService.uploadAttachment(file, newFileEntity, scope.fileEntityPath)\r\n .then(uploadComplete, uploadFailed, uploadProgress);\r\n } else {\r\n if (item.id) {\r\n $.extend(item, newFileEntity);\r\n $http.put(scope.fileEntityPath, newFileEntity);\r\n } else {\r\n scope.files.push(newFileEntity);\r\n $http.post(scope.fileEntityPath, newFileEntity);\r\n }\r\n }\r\n }, { name: item.filePath, isFromMedia: true }, item.name, item.description, item.source);\r\n };\r\n\r\n scope.delete = item => {\r\n this.dialogService.confirm(loc.msg_confirmdelete, () => {\r\n scope.files.remove(item);\r\n this.$http.delete(scope.fileEntityPath + \"/\" + item.id);\r\n });\r\n };\r\n };\r\n }\r\n\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { IFieldController } from \"@app/components/kb-field/kb-field.component\";\r\n\r\nexport interface IInputScope extends ng.IScope {\r\n ngModel: any;\r\n /** pass through ngChange capability */\r\n ngChange?: () => void;\r\n /** pass through for ngDisabled */\r\n ngDisabled: boolean;\r\n ngModelOptions: any;\r\n\r\n /** when one of our directives is used as a child of another, we probably want it to ignore the parent KbField\r\n * (like checkboxes in an image multi-select). Otherwise, the checkbox will find the parent field and\r\n * mess with it's settings when it shouldn't. To stop this, set ignoreField to true.\r\n */\r\n ignoreField?: boolean;\r\n\r\n /** called once there has been a blur event to track whether the user has interacted with the control */\r\n touched: () => void;\r\n\r\n _ngChange: () => void;\r\n _setHasValue: (hasValue: boolean) => void;\r\n\r\n textColor?: string;\r\n backgroundColor?: string;\r\n}\r\n\r\n/**\r\n * Acts as a base class to directives that work together with kbField to manage focus and common setup\r\n */\r\nexport class KbInput extends Directive {\r\n constructor(public $timeout: ng.ITimeoutService) {\r\n super();\r\n this.restrict = \"E\";\r\n this.replace = true;\r\n this.scope = {\r\n ngModel: \"=\",\r\n ngDisabled: \"=?\",\r\n ngModelOptions: \"=?\",\r\n ngChange: \"&\",\r\n ngBlur: \"&\",\r\n touched: \"&\",\r\n ignoreField: \"=?\",\r\n textColor: \"=?\",\r\n backgroundColor: \"=?\",\r\n heightOverride: \"=?\"\r\n }\r\n\r\n this.require = [\"ngModel\", \"?^^kbField\"];\r\n this.link = (s, e, a, c) => this.kbInputLinkFn(s as IInputScope, e, a, c);\r\n }\r\n\r\n public kbInputLinkFn(scope: IInputScope, element: ng.IAugmentedJQuery, atts: ng.IAttributes, controllers: any[], shouldFloat: boolean = true, isEmpty?: (val: any) => boolean) {\r\n let ngModelCtrl = controllers[0] as ng.INgModelController;\r\n let kbField: IFieldController = null;\r\n if (!scope.ignoreField) {\r\n kbField = controllers.length > 1 ? controllers.last() : null;\r\n }\r\n\r\n if (kbField) { //register our input ngModel with kbField\r\n kbField.setShouldFloat(shouldFloat);\r\n }\r\n\r\n if (!isEmpty) {\r\n isEmpty = (val) => {\r\n return (val == null || val.toString().length == 0);\r\n };\r\n }\r\n\r\n let ngModelPipelineCheckValue = (val) => {\r\n if (kbField) kbField.setHasValue(!isEmpty(val) && !(Array.isArray(val) && !val.length));\r\n return val;\r\n }\r\n\r\n ngModelCtrl.$parsers.push(ngModelPipelineCheckValue);\r\n ngModelCtrl.$formatters.push(ngModelPipelineCheckValue);\r\n ngModelCtrl.$viewChangeListeners.push(() => {\r\n //for some controls, blur is not the right time to consider whether the control has been touched (like select controls).\r\n //so we also track it here.\r\n if (scope.touched) {\r\n scope.touched();\r\n }\r\n });\r\n\r\n\r\n let focusin = (e: JQueryEventObject) => {\r\n if (kbField) kbField.setFocused(true);\r\n };\r\n let focusout = () => {\r\n if (kbField) {\r\n kbField.setFocused(false);\r\n }\r\n if (scope.touched) {\r\n scope.touched();\r\n }\r\n }\r\n element.on(\"focusin\", focusin);\r\n element.on(\"focusout\", focusout);\r\n\r\n // for some reason the ngChange is getting run before the model in the parent controller\r\n // is being updated by the value change, so we need to do this trick to wait until\r\n // everything is done before firing the ng-change\r\n scope._ngChange = () => {\r\n this.$timeout(() => {\r\n scope.ngChange();\r\n }, 0);\r\n };\r\n\r\n // bind keyboard event: esc(27)\r\n let el = element;\r\n if (!el.is(\"input\")) {\r\n el = el.find(\"input\");\r\n }\r\n if (el && el.length > 0) {\r\n el.on(\"keydown\", (e: JQueryEventObject) => {\r\n if (e.which == 27) {\r\n el.blur();\r\n }\r\n });\r\n }\r\n\r\n scope._setHasValue = (hasValue) => {\r\n if (kbField) {\r\n kbField.setHasValue(hasValue);\r\n }\r\n };\r\n\r\n scope.$on(\"$destroy\", () => {\r\n if (kbField) {\r\n kbField.setFocused(false);\r\n kbField.setHasValue(false);\r\n }\r\n element.off();\r\n });\r\n }\r\n}\r\n","import { IInputScope, KbInput } from \"@app/components/kb-input/kb-input.component\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { Utils } from \"@tools\";\r\n\r\nexport interface IAutoCompleteScope extends IInputScope {\r\n /**\r\n * the query for data....(query:string) => ng.IPromise\r\n */\r\n source: any;\r\n /**\r\n * custom data that can be passed in and accessed by the transcluded content for the select items\r\n */\r\n data: any;\r\n /**\r\n * query to get the label of a value. Needed when the field you're querying is not\r\n * the same as the value field: (value: string) => ng.IPromise\r\n */\r\n getLabel: any;\r\n /**\r\n * whether it should constrain values to those from the source\r\n */\r\n editable: boolean;\r\n /**\r\n * needed for comparison to hide already selected items from the dropdown\r\n */\r\n valueField: string;\r\n labelField: string;\r\n itemStyle: string;\r\n /**\r\n * whether the number of remote queries is rate-limited; defaults to false\r\n */\r\n throttle: string;\r\n /**\r\n * the minimum number of characters typed by the user before autocompletion kicks in. Defaults to 0;\r\n */\r\n minCharacters: number;\r\n /**\r\n * an optional icon to show inside the auto-complete (used for search boxes)\r\n */\r\n icon: string;\r\n /**\r\n * happens when the user explicitly presses enter or selects an option from the dropdown \r\n * (won't fire when just losing focus). This is used by the search.\r\n */\r\n submit: (q: { item: any }) => void; //\r\n placeholder: string;\r\n mobileDropdown: boolean;\r\n\r\n // internal directive members\r\n _matches: any[];\r\n _activeIndex: number;\r\n _select: (item: any) => void;\r\n _focus: (e: ng.IAngularEvent) => void;\r\n _blur: (e: ng.IAngularEvent) => void;\r\n _dropdownOpen: boolean;\r\n _label: string;\r\n _inputChange: (e: ng.IAngularEvent) => void;\r\n _hint: string; // if the user is typing an exact match, will show the rest of the word (like google)\r\n _id: string;\r\n _isActive: (index) => boolean;\r\n _itemMousedown: (e: JQueryEventObject, item: any) => void;\r\n _inProgress: boolean; // tracking remote calls to show loading animation\r\n}\r\n\r\nexport interface IKbAutoCompleteController {\r\n scope: IAutoCompleteScope;\r\n}\r\n\r\n@NgComponent({\r\n token: Token.KbAutoComplete,\r\n dependencies: [\r\n Token.$Q,\r\n Token.$Http,\r\n Token.$Timeout,\r\n ]\r\n})\r\nexport class KbAutoComplete extends KbInput {\r\n\r\n constructor($q: ng.IQService, $http: ng.IHttpService, $timeout: ng.ITimeoutService) {\r\n super($timeout);\r\n\r\n this.template = Dirs.component(\"kb-auto-complete\");\r\n this.scope = Utils.extend(this.scope, {\r\n source: \"&\",\r\n data: \"=?\",\r\n getLabel: \"&\",\r\n editable: \"=?\",\r\n valueField: \"@\",\r\n labelField: \"@\",\r\n defaultLabel: \"@\",\r\n headerTemplate: \"@\",\r\n itemStyle: \"@\",\r\n throttle: \"@\",\r\n minCharacters: \"=?\",\r\n icon: \"@\",\r\n submit: \"&\",\r\n placeholder: \"@\",\r\n mobileDropdown: \"=?\",\r\n });\r\n this.transclude = true;\r\n\r\n this.compile = (element, atts: any) => {\r\n if (atts.mobileDropdown == null) atts.mobileDropdown = \"true\";\r\n return this.link;\r\n };\r\n\r\n this.link = (scope: IAutoCompleteScope, element: JQuery, atts, controllers: any[]) => {\r\n this.kbInputLinkFn(scope, element, atts, controllers, true, (val => false));\r\n let ngModel = controllers[0];\r\n let input = element.find(\"input\");\r\n scope._id = Utils.shortId();\r\n let hintItem: any; // the data item that is being used to show the current hint\r\n\r\n let toStringSafe = (o: any) => {\r\n if (o == null) return null;\r\n return o.toString();\r\n };\r\n\r\n let getItemValue = (item: any) => {\r\n if (item === null || item === undefined) return null;\r\n return scope.valueField ? item[scope.valueField] : item;\r\n };\r\n let getItemLabel = (item: any): string => {\r\n let l;\r\n if (item != null) {\r\n if (scope.labelField && item[scope.labelField]) {\r\n l = item[scope.labelField];\r\n } else if (scope.valueField) {\r\n l = item[scope.valueField];\r\n } else {\r\n l = item;\r\n }\r\n }\r\n return toStringSafe(l);\r\n };\r\n\r\n let isEnabled = () => {\r\n return !scope.ngDisabled;\r\n };\r\n \r\n let setLabelForValue = (): ng.IPromise => {\r\n // if the labelField is being used, then we need to make a \r\n // call to the consumer to get the label for the value\r\n if (scope.labelField) {\r\n // first we try to find if we already have a match in our _matches to get the label from there\r\n // if not, then we make a call to the consumer to retrieve it\r\n let match = scope._matches ? scope._matches.find(m => getItemValue(m) == ngModel.$viewValue) : null;\r\n if (match) {\r\n scope._label = getItemLabel(match);\r\n } else {\r\n return $q.when(scope.getLabel({ value: ngModel.$viewValue })).then(l => {\r\n scope._label = l;\r\n });\r\n }\r\n } else { // no label-field is being used, so we just set the text input to the value\r\n scope._label = ngModel.$viewValue;\r\n }\r\n };\r\n\r\n ngModel.$render = () => { // called when the binding has been changed by the consumer\r\n setLabelForValue();\r\n };\r\n\r\n scope._itemMousedown = (e, item) => {\r\n e.preventDefault(); // so we don't lose focus and trigger the blur event\r\n scope._select(item);\r\n // call submit for search boxes\r\n if (scope.submit) scope.submit({ item });\r\n };\r\n\r\n scope._select = item => {\r\n if (isEnabled()) {\r\n hideDropdown();\r\n ngModel.$setViewValue(getItemValue(item));\r\n scope._label = getItemLabel(item);\r\n scope._hint = null;\r\n hintItem = null;\r\n $timeout(() => {\r\n suppressFocusEvent = true;\r\n input.focus();\r\n // suppressFocusEvent = false;\r\n }, 0);\r\n }\r\n };\r\n \r\n let showDropdown = () => {\r\n // scope._activeIndex = 0;\r\n scope._dropdownOpen = true;\r\n };\r\n let hideDropdown = () => {\r\n scope._dropdownOpen = false;\r\n };\r\n \r\n scope._isActive = index => {\r\n return index === scope._activeIndex;\r\n };\r\n \r\n let throttle = scope.throttle ? (scope.throttle == \"true\") : false;\r\n let getMatches = Utils.throttle(() => {\r\n if (isEnabled()) {\r\n var query = toStringSafe(scope._label);\r\n if (query && (!scope.minCharacters || query.length >= scope.minCharacters)){\r\n scope._inProgress = true;\r\n return $q.when(scope.source({ query })).then((result: any[]) => {\r\n scope._matches = result;\r\n if (scope._matches && scope._matches.length) showDropdown();\r\n scope._hint = null;\r\n hintItem = null;\r\n if (scope._label) {\r\n // if the first match is an exact match so far, then show the hint\r\n if (scope._matches && scope._matches.length) {\r\n let o = scope._matches[0];\r\n let l = getItemLabel(o);\r\n if (l && l.toString().toLowerCase().startsWith(scope._label.toLowerCase())) {\r\n // match the case of whatever the user has already typed\r\n scope._hint = scope._label + l.substr(scope._label.length);\r\n hintItem = o;\r\n }\r\n scope._activeIndex = 0;\r\n } else {\r\n scope._activeIndex = -1;\r\n }\r\n scope._activeIndex = scope.editable ? -1 : 0;\r\n }\r\n }).finally(() => {\r\n scope._inProgress = false;\r\n });\r\n }\r\n }\r\n }, throttle ? 300 : 0);\r\n\r\n let suppressFocusEvent = false;\r\n scope._focus = e => {\r\n if (!suppressFocusEvent && !scope._dropdownOpen) {\r\n getMatches();\r\n }\r\n suppressFocusEvent = false;\r\n };\r\n scope._blur = e => {\r\n // if this is editable, then set ngModel to whatever the user typed in when the input loses focus\r\n // also when a labelField is declared, it CAN'T be editable\r\n if (scope.editable) {\r\n ngModel.$setViewValue(scope._label);\r\n } else {\r\n setLabelForValue();\r\n }\r\n scope._hint = null;\r\n hintItem = null;\r\n };\r\n\r\n scope._inputChange = e => {\r\n getMatches();\r\n };\r\n\r\n let buildItem = val => {\r\n let item = null;\r\n if (scope._activeIndex > -1) {\r\n item = scope._matches[scope._activeIndex];\r\n } else if (scope.valueField) {\r\n item = {};\r\n item[scope.valueField] = val;\r\n } else {\r\n item = val;\r\n }\r\n return item;\r\n };\r\n\r\n let moveUp = () => {\r\n if (scope._dropdownOpen) {\r\n // if we are already at index zero, then close the dropdown\r\n let newIndex = scope._activeIndex - 1;\r\n if (newIndex >= 0) scope._activeIndex = newIndex;\r\n }\r\n };\r\n\r\n let moveDown = () => {\r\n showDropdown();\r\n // if we are already at index zero, then close the dropdown\r\n let newIndex = scope._activeIndex + 1;\r\n if (newIndex < scope._matches.length) scope._activeIndex = newIndex;\r\n };\r\n \r\n // bind keyboard events: arrows up(38) / down(40), enter(13) and tab(9), esc(27)\r\n element.on(\"keydown\", (e: JQueryEventObject) => {\r\n\r\n if (e.which == 38) {\r\n e.preventDefault();\r\n scope.$apply(() => {\r\n moveUp();\r\n });\r\n }\r\n if (e.which == 40) {\r\n e.preventDefault();\r\n scope.$apply(() => {\r\n moveDown();\r\n });\r\n }\r\n if (e.which == 9 || e.which == 13) {\r\n scope.$apply(() => {\r\n let item = buildItem(scope._label);\r\n if ((scope._dropdownOpen && scope._activeIndex > -1) || scope.editable) {\r\n scope._select(item);\r\n e.stopPropagation();\r\n } else {\r\n hideDropdown();\r\n scope._blur(null);\r\n }\r\n\r\n // call submit for search boxes \r\n if (scope.submit) {\r\n scope.submit({ item });\r\n }\r\n });\r\n }\r\n if (e.which == 27) {\r\n e.preventDefault();\r\n scope.$apply(() => {\r\n hideDropdown();\r\n e.stopPropagation();\r\n });\r\n }\r\n });\r\n\r\n scope.$on(\"$destroy\", () => {\r\n element.off();\r\n });\r\n };\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { IProfileImageFilter } from \"@app/filters/profile-image.filter\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { ApiService } from \"@app/services/api.service\";\r\nimport { KbService } from \"@app/services/kb.service\";\r\nimport { UploadService } from \"@app/services/upload.service\";\r\nimport { IRootScope } from \"@models\";\r\nimport { events } from \"@tools\";\r\n\r\nexport interface IAvatarSelectScope extends ng.IScope {\r\n ngModel: string;\r\n userId: number;\r\n imgPath: string;\r\n isEnabled: () => boolean;\r\n clear: () => void;\r\n click: () => void;\r\n}\r\n\r\n@NgComponent({\r\n token: Token.KbAvatarSelect,\r\n dependencies: [\r\n Token.KbService,\r\n Token.$RootScope,\r\n Token.UploadService,\r\n Token.$Filter,\r\n Token.ApiService,\r\n ]\r\n})\r\nexport class KbAvatarSelect extends Directive {\r\n constructor(\r\n kbService: KbService,\r\n $rootScope: IRootScope,\r\n uploadService: UploadService,\r\n $filter: ng.IFilterService,\r\n apiService: ApiService\r\n ) {\r\n super();\r\n this.replace = true;\r\n this.restrict = \"E\";\r\n this.scope = {\r\n ngModel: \"=\",\r\n userId: \"=\"\r\n };\r\n this.template = Dirs.component(\"kb-avatar-select\");\r\n\r\n this.link = (scope: IAvatarSelectScope, element, atts, ngModelController: ng.INgModelController) => {\r\n scope.isEnabled = () => {\r\n return !($(element).hasClass(\"disabled\") || $(element).attr(\"disabled\"));\r\n };\r\n\r\n scope.imgPath = (($filter as any)(\"profileImage\") as IProfileImageFilter)(scope.ngModel);\r\n\r\n scope.clear = () => {\r\n apiService.users.clearProfileImage(scope.userId).then(user => {\r\n scope.ngModel = user.imagePath;\r\n scope.imgPath = user.imagePath;\r\n if (scope.userId == $rootScope.user.id) {\r\n $rootScope.$broadcast(events.avatarChanged, scope.ngModel);\r\n }\r\n });\r\n };\r\n\r\n scope.click = () => {\r\n if (scope.isEnabled()) {\r\n uploadService.promptUserToChooseFile(\"image/*\").then(file => {\r\n uploadService.uploadProfileImage(file, scope.userId).then(() => {\r\n scope.ngModel = scope.userId.toString();\r\n scope.imgPath = (($filter as any)(\"profileImage\") as IProfileImageFilter)(scope.ngModel);\r\n if (scope.userId == $rootScope.user.id) {\r\n $rootScope.$broadcast(events.avatarChanged, scope.ngModel);\r\n }\r\n });\r\n });\r\n }\r\n };\r\n };\r\n }\r\n}\r\n","import { events } from \"@tools\";\r\nimport { Directive } from \"@app/components/directive\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { IRootScope } from \"@models\";\r\nimport { DialogService } from \"@app/services/dialog.service\";\r\n\r\n@NgComponent({\r\n token: Token.KbAvatar,\r\n dependencies: [\r\n Token.$RootScope,\r\n Token.DialogService,\r\n Token.$Http,\r\n ]\r\n})\r\nexport class KbAvatar extends Directive {\r\n constructor(\r\n private $rootScope: IRootScope,\r\n private dialogService: DialogService,\r\n private $http: ng.IHttpService\r\n ) {\r\n super();\r\n\r\n this.replace = true;\r\n this.template = Dirs.component(\"kb-avatar\");\r\n this.restrict = \"E\";\r\n this.scope = {\r\n path: \"=\"\r\n };\r\n\r\n this.link = (scope, element, atts) => {\r\n $rootScope.$on(events.avatarChanged, (e, newPath) => {\r\n // Adding a hash to force the model to change (otherwise the image will not\r\n // auto-load, assuming the newPath has not changed (but the data has)\r\n (scope as any).path = newPath + \"#\" + (new Date()).getTime().toString();\r\n });\r\n };\r\n }\r\n\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\n\r\n@NgComponent({\r\n token: Token.KbButton\r\n})\r\nexport class KbButton extends Directive {\r\n constructor($timeout: ng.ITimeoutService) {\r\n super();\r\n this.restrict = \"E\";\r\n this.replace = true;\r\n this.transclude = true;\r\n this.scope = {\r\n ngClick: \"&\",\r\n textColor: \"=?\",\r\n backgroundColor: \"=?\"\r\n }\r\n\r\n this.template = Dirs.component(\"kb-button\");\r\n }\r\n}\r\n","import { IInputScope, KbInput } from \"@app/components/kb-input/kb-input.component\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { Utils } from \"@tools\";\r\n\r\ninterface ICheckboxScope extends IInputScope {\r\n inputId?: string;\r\n}\r\n \r\n/**\r\n * KbCheckbox\r\n *\r\n * pass in an inputId to explicitly set the checkbox input with an id,\r\n * otherwise if its in a kbfield will use a guid that was generated by the kbField\r\n * if there is no ngModel and no id provided, it will create it's own guid\r\n */\r\n@NgComponent({\r\n token: Token.KbCheckbox,\r\n dependencies: [\r\n Token.$Timeout\r\n ]\r\n})\r\nexport class KbCheckbox extends KbInput {\r\n constructor($timeout: ng.ITimeoutService) {\r\n super($timeout);\r\n this.scope = Utils.extend(this.scope, {\r\n inputId: \"=?\"\r\n });\r\n this.template = Dirs.component(\"kb-checkbox\");\r\n\r\n this.link = (scope: ICheckboxScope, element: JQuery, atts: any, controllers: any[]) => {\r\n this.kbInputLinkFn(scope, element, atts, controllers);\r\n let ngModel = controllers[0];\r\n let kbField = controllers.length > 1 ? controllers[1] : null;\r\n\r\n if (atts.inputId) {\r\n // do nothing, use the inputid as is\r\n } else if (kbField && atts.ngModel) {\r\n // if we're inside a kbfield, then tie the labels together with the same id \r\n scope.inputId = Utils.shortId();\r\n if (!scope.ignoreField) {\r\n kbField.scope.isCheckbox = true;\r\n kbField.scope._checkboxId = scope.inputId;\r\n } \r\n } else {\r\n scope.inputId = Utils.shortId();\r\n }\r\n\r\n if (!scope.inputId) {\r\n throw new Error(\"empty checkbox id\");\r\n }\r\n\r\n element.on(\"keydown\", (e: JQueryEventObject) => {\r\n if (e.which == 13 || e.which == 32 && !scope.ngDisabled) {\r\n scope.$apply(() => {\r\n scope.ngModel = !scope.ngModel;\r\n scope.ngChange();\r\n });\r\n e.preventDefault();\r\n }\r\n else if (e.which == 27) {\r\n element.blur();\r\n }\r\n });\r\n\r\n scope.$on(\"$destroy\", () => {\r\n element.off();\r\n });\r\n };\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\n\r\nexport interface IColorPickerScope extends ng.IScope {\r\n ngModel: string;\r\n}\r\n\r\n@NgComponent({\r\n token: Token.KbColorPicker,\r\n dependencies: [\r\n Token.$Timeout\r\n ]\r\n})\r\nexport class KbColorPicker extends Directive {\r\n constructor($timeout: ng.ITimeoutService) {\r\n super();\r\n this.restrict = \"E\";\r\n this.replace = true;\r\n this.scope = {\r\n ngModel: \"=\"\r\n };\r\n this.require = \"?ngModel\";\r\n\r\n this.template = Dirs.component(\"kb-color-picker\");\r\n\r\n this.link = (\r\n scope: IColorPickerScope,\r\n element: ng.IAugmentedJQuery,\r\n atts: ng.IAttributes,\r\n ngModel: ng.INgModelController\r\n ) => {\r\n\r\n element.minicolors({\r\n control: \"hue\",\r\n defaultValue: scope.ngModel || \"\",\r\n inline: false,\r\n letterCase: \"lowercase\",\r\n opacity: true,\r\n position: \"bottom left\",\r\n change: newValue => {\r\n scope.$apply(() => {\r\n ngModel.$setViewValue(newValue);\r\n });\r\n }\r\n });\r\n element.parent().addClass(\"kb-color-picker\");\r\n element.parent().append('
');\r\n\r\n ngModel.$render = () => {\r\n $timeout(() => {\r\n element.minicolors(\"value\", ngModel.$viewValue || \"\");\r\n }, 0, false);\r\n };\r\n\r\n scope.$on(\"$destroy\", () => {\r\n element.minicolors(\"destroy\" as any);\r\n });\r\n };\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\n\r\nexport interface IColumnScope extends ng.IScope {\r\n // interface\r\n label: string;\r\n id: string;\r\n field: string;\r\n /**the order in which the columns should show up in the grid. We need this because kb-if will delay the initialization of kb-column, making them out of order */\r\n order: number;\r\n\r\n // internal\r\n colClass: string;\r\n style: any;\r\n // toggleSort: () => void;\r\n sortable: boolean;\r\n sorted: boolean;\r\n descending: boolean;\r\n show: () => boolean;\r\n getClass: () => string;\r\n getStyle: () => string;\r\n}\r\n \r\n@NgComponent({\r\n token: Token.KbColumn,\r\n dependencies: [\r\n ]\r\n})\r\nexport class KbColumn extends Directive {\r\n constructor() {\r\n super();\r\n\r\n this.require = [\"^?kbSearchGrid\", \"^?kbDataGrid\"];\r\n this.replace = true;\r\n this.template = Dirs.component(\"kb-column\");\r\n this.restrict = \"AE\";\r\n this.scope = {\r\n label: \"@\",\r\n id: \"@\",\r\n field: \"@\",\r\n sortable: \"=?\",\r\n toggleSort: \"&\",\r\n order: \"=?\"\r\n };\r\n this.transclude = true;\r\n this.link = (scope: IColumnScope, element: ng.IAugmentedJQuery, atts: any, gridCtrl) => {\r\n if (scope.sortable == null) scope.sortable = true;\r\n gridCtrl = gridCtrl[0] ? gridCtrl[0] : gridCtrl[1];\r\n\r\n gridCtrl.addColumn(scope);\r\n\r\n scope.show = () => {\r\n return ((typeof (atts.kbIf) == \"undefined\") || scope.$parent.$eval(atts.kbIf) != false);\r\n };\r\n\r\n scope.getClass = () => {\r\n return element.attr(\"class\");\r\n };\r\n\r\n scope.getStyle = () => {\r\n return element.attr(\"style\");\r\n };\r\n };\r\n\r\n }\r\n\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { AuthService } from \"@app/services/auth.service\";\r\nimport { DialogService } from \"@app/services/dialog.service\";\r\nimport { eInputDialogType, IComment, InputDialogButton, IRootScope } from \"@models\";\r\nimport { icons } from \"@tools\";\r\nimport * as angular from \"angular\";\r\n\r\nexport interface ICommentsScope extends ng.IScope {\r\n objectId?: number;\r\n tableName?: string;\r\n api?: ICommentsApi;\r\n\r\n _comments?: IComment[];\r\n _delete: (item: IComment) => void;\r\n _cancel: () => void;\r\n _addComment: () => void;\r\n _edit: (item: IComment) => void;\r\n _model: any;\r\n}\r\n\r\nexport interface ICommentsApi {\r\n refresh?: () => void;\r\n}\r\n\r\n@NgComponent({\r\n token: Token.KbComments,\r\n dependencies: [\r\n Token.$RootScope,\r\n Token.DialogService,\r\n Token.$Http,\r\n Token.AuthService,\r\n ]\r\n})\r\nexport class KbComments extends Directive {\r\n constructor(\r\n private $rootScope: IRootScope,\r\n private dialogService: DialogService,\r\n private $http: ng.IHttpService,\r\n private authService: AuthService\r\n ) {\r\n super();\r\n\r\n this.replace = false;\r\n this.template = Dirs.component(\"kb-comments\");\r\n this.restrict = \"E\";\r\n this.scope = {\r\n objectId: \"=\",\r\n tableName: \"@\",\r\n api: \"=?\"\r\n };\r\n\r\n this.link = (scope: ICommentsScope, element, atts: any) => {\r\n if (!angular.isDefined(scope.api)) {\r\n scope.api = {};\r\n }\r\n\r\n scope._comments = [];\r\n\r\n scope.api.refresh = () => {\r\n // get the comments for this object\r\n if (angular.isDefined(scope.objectId) && $rootScope.user.canViewComments) {\r\n this.$http.get(\"/api/comments\", {\r\n params: {\r\n objectId: scope.objectId,\r\n tableName: scope.tableName\r\n }\r\n } as ng.IRequestConfig).then(r => {\r\n scope._comments = r.data ? r.data : [];\r\n });\r\n }\r\n };\r\n scope.api.refresh();\r\n\r\n scope._delete = item => {\r\n scope._comments.remove(item);\r\n this.$http.delete(\"/api/comments/\" + item.id);\r\n };\r\n\r\n scope._model = { text: \"\" };\r\n\r\n scope._cancel = () => {\r\n scope._model.text = \"\";\r\n };\r\n\r\n scope._addComment = () => {\r\n\r\n let newComment: IComment = {\r\n idUser: $rootScope.user.id,\r\n tableName: scope.tableName,\r\n body: scope._model.text,\r\n createdByName: $rootScope.user.firstName + \" \" + $rootScope.user.lastName,\r\n createdByImagePath: $rootScope.user.imagePath\r\n };\r\n\r\n this.$http.post(\"/api/comments/\" + scope.objectId, newComment).then(r => {\r\n scope._comments.push(r.data);\r\n scope._model.text = \"\";\r\n });\r\n };\r\n\r\n scope._edit = (item: IComment) => {\r\n dialogService.input({\r\n msg: \"Comment Edit\",\r\n inputType: eInputDialogType.textArea,\r\n value: item.body,\r\n buttons: [\r\n new InputDialogButton(loc.ok, icons.success, args => {\r\n item.body = args.value;\r\n this.$http.put(\"/api/comments/\" + item.id, item).then(r => {\r\n\r\n });\r\n }),\r\n new InputDialogButton(loc.cancel, icons.cancel, args => {\r\n\r\n })\r\n ]\r\n });\r\n };\r\n };\r\n }\r\n\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\n@NgComponent({\r\n token: Token.KbContent\r\n})\r\nexport class KbContent extends Directive {\r\n constructor() {\r\n super();\r\n\r\n this.restrict = \"A\";\r\n this.scope = false;\r\n\r\n this.link = (scope: any, element, atts: any) => {\r\n element.addClass(\"ng-binding\").data(\"$binding\", atts.kbContent);\r\n scope.$watch(atts.kbContent, value => {\r\n element.html(value || \"\");\r\n });\r\n };\r\n\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\n@NgComponent({\r\n token: Token.KbDataGrid,\r\n dependencies: [\r\n ]\r\n})\r\nexport class KbDataGrid extends Directive {\r\n constructor() {\r\n super();\r\n\r\n this.replace = true;\r\n this.template = Dirs.component(\"kb-data-grid\");\r\n this.restrict = \"AE\";\r\n this.scope = false;\r\n this.transclude = true;\r\n\r\n this.controller = [\"$scope\", \"$element\", function($scope, $element) {\r\n let columns = $scope.columns = [];\r\n\r\n this.addColumn = column => {\r\n let exists: boolean = columns.some(c => c.id == column.id);\r\n if (!exists) {\r\n columns.push(column);\r\n column.$on(\"$destroy\", event => {\r\n columns.remove(column);\r\n });\r\n }\r\n };\r\n }];\r\n this.link = (scope: any, element, atts: any) => {\r\n scope.ngModel = scope.$eval(atts.ngModel);\r\n };\r\n\r\n }\r\n\r\n}\r\n","import { IInputScope, KbInput } from \"@app/components/kb-input/kb-input.component\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { Utils } from \"@tools\";\r\nimport flatpickr from \"flatpickr\";\r\n\r\nexport interface IDatePickerScope extends IInputScope {\r\n // external members\r\n minDate: Date;\r\n maxDate: Date;\r\n format: string;\r\n enableTime: boolean;\r\n\r\n _clear: () => void;\r\n}\r\n\r\n@NgComponent({\r\n token: Token.KbDatePicker,\r\n dependencies: [\r\n Token.$Timeout\r\n ]\r\n})\r\nexport class KbDatePicker extends KbInput {\r\n constructor($timeout: ng.ITimeoutService) {\r\n super($timeout);\r\n\r\n this.template = Dirs.component(\"kb-date-picker\");\r\n this.scope = Utils.extend(this.scope, {\r\n minDate: \"=?\",\r\n maxDate: \"=?\",\r\n format: \"=?\",\r\n enableTime: \"=?\"\r\n });\r\n\r\n this.link = (scope: IDatePickerScope, element: JQuery, atts, controllers: any[]) => {\r\n this.kbInputLinkFn(scope, element, atts, controllers);\r\n let ngModel = controllers[0];\r\n\r\n let input = element.find(\"input\")[0] as HTMLInputElement;\r\n let picker = flatpickr(input, {\r\n onChange: () => {\r\n ngModel.$setViewValue(picker.parseDate(input.value) || null);\r\n },\r\n enableTime: !!scope.enableTime\r\n }) as flatpickr.Instance;\r\n\r\n ngModel.$render = () => {\r\n picker.setDate(ngModel.$viewValue);\r\n };\r\n\r\n scope.$watch(\"minDate\", (newValue, oldValue) => {\r\n picker.set(\"minDate\", newValue);\r\n });\r\n scope.$watch(\"maxDate\", (newValue, oldValue) => {\r\n picker.set(\"maxDate\", newValue);\r\n });\r\n scope.$watch(\"format\", (newValue, oldValue) => {\r\n picker.set(\"dateFormat\", newValue || \"Y-m-d\");\r\n picker.setDate(ngModel.$viewValue, false); // set the date to update the format in the input\r\n });\r\n scope.$watch(\"enableTime\", (newValue, oldValue) => {\r\n picker.set(\"enableTime\", !!newValue);\r\n });\r\n\r\n scope._clear = () => {\r\n picker.clear();\r\n };\r\n scope.$on(\"$destroy\", () => {\r\n if (picker) {\r\n picker.destroy();\r\n }\r\n element.off();\r\n });\r\n };\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { eScrollMode, Utils } from \"@tools\";\r\nimport * as angular from \"angular\";\r\nimport Tether, { ITetherConstraint } from \"tether\";\r\n\r\ninterface IDropdownScope extends ng.IScope {\r\n open?: boolean;\r\n scrollTo?: string;\r\n autoDirection?: boolean;\r\n horizontalAlign: string; // left, right, or undefined\r\n verticalAlign: string; // top, bottom, or undefined. Defaults to bottom\r\n height: string; // defaults to auto\r\n width: string; // defaults to auto\r\n animate: boolean;\r\n ignoreClickOn: string; // selector of an element(s) that when clicked should not result in the dropdown closing\r\n ignoreClickOnParent: string; // same as above, but selector for parents of elements that are clicked on\r\n}\r\n\r\n@NgComponent({\r\n token: Token.KbDropdown,\r\n dependencies: [\r\n Token.$Timeout\r\n ]\r\n})\r\nexport class KbDropdown extends Directive {\r\n constructor($timeout: ng.ITimeoutService) {\r\n super();\r\n\r\n this.restrict = \"EA\";\r\n this.scope = {\r\n open: \"=\",\r\n scrollTo: \"@\",\r\n autoDirection: \"=\",\r\n horizontalAlign: \"@\",\r\n verticalAlign: \"@\",\r\n height: \"@\",\r\n width: \"@\",\r\n animate: \"@\",\r\n ignoreClickOn: \"@\",\r\n ignoreClickOnParent: \"@\"\r\n };\r\n this.replace = true;\r\n this.transclude = true;\r\n this.template = `\r\n
\r\n
\r\n
\r\n
`;\r\n\r\n this.link = (scope: IDropdownScope, element: JQuery, atts: any) => {\r\n let timeouts: ng.IPromise[] = [];\r\n let guid = Utils.shortId();\r\n let $parent = $(element).parent();\r\n let openIsDefined = angular.isDefined(atts.open);\r\n let hAlign = scope.horizontalAlign || \"left\";\r\n let vAlign = scope.verticalAlign || \"bottom\";\r\n let vAlignOpposite = vAlign == \"top\" ? \"bottom\" : \"top\";\r\n let isVisible = false;\r\n\r\n // if height is set, make the dropdown scrollable\r\n if (scope.height && scope.height != 'auto') element.addClass(\"kb-dropdown--scrollable\");\r\n let height = scope.height || \"auto\"; \r\n element.css(\"max-height\", height);\r\n \r\n\r\n // define a tether\r\n let tether: Tether;\r\n let createTether = () => {\r\n if (!tether) {\r\n let options = {\r\n element,\r\n target: $parent,\r\n attachment: vAlignOpposite + \" \" + hAlign,\r\n targetAttachment: vAlign + \" \" + hAlign,\r\n constraints: [\r\n {\r\n to: document as any,\r\n attachment: \"together\",\r\n pin: [\"left\",\"right\"]\r\n } as ITetherConstraint\r\n ],\r\n classes: {\r\n tether: false,\r\n element: false,\r\n target: false,\r\n enabled: false,\r\n // 'element-attached': false,\r\n // 'target-attached': false,\r\n // 'abutted': false\r\n }\r\n } as Tether.ITetherOptions;\r\n \r\n // if the dropdown is part of a hotspot, and we are in XR, then we need to add to the hotspot div instead of body\r\n let p = element[0].closest(\".xr-overlay\") as HTMLElement;\r\n if (p){\r\n options.bodyElement = p;\r\n }\r\n \r\n tether = new Tether(options);\r\n }\r\n };\r\n\r\n let scrollToActive = () => {\r\n if (isVisible && scope.scrollTo && scope.scrollTo.length > 1) {\r\n let $item = element.find(scope.scrollTo);\r\n if ($item.length > 0) {\r\n Utils.scrollIntoView({ elem: $item[0], mode: eScrollMode.middleIfNecessary, animate: false });\r\n }\r\n }\r\n };\r\n\r\n scope.$watch(\"scrollTo\", newValue => {\r\n scrollToActive();\r\n });\r\n\r\n let preventScroll = (e: Event) => {\r\n if (e.target == document.body) e.preventDefault();\r\n };\r\n\r\n let hideDropdown = () => {\r\n if (!isVisible) return;\r\n isVisible = false;\r\n\r\n //stage the close so CSS can animate it\r\n $parent.removeClass(\"is-open\");\r\n element.removeClass(\"is-open\");\r\n\r\n setTimeout(() => {\r\n element.css(\"display\", \"none\");\r\n }, 366)\r\n\r\n document.removeEventListener(\"click\", onDocumentClicked, true);\r\n document.body.removeEventListener(\"touchmove\", preventScroll);\r\n };\r\n\r\n // let hideDropdown = () => {\r\n // if (!isVisible) return;\r\n // isVisible = false;\r\n // // setting to false so that in configurators, we're not waiting for the dropdown \r\n // // to close while the scene is being updated.Makes it feel sluggish\r\n // // var animate = false; //!element.hasClass(\"tether-element-attached-bottom\");\r\n // let afterAnimation = () => {\r\n // element.css(\"display\", \"none\");\r\n // element.css(\"height\", \"auto\");\r\n // $parent.removeClass(\"is-open\");\r\n // };\r\n\r\n // if (scope.animate) {\r\n // element.animate({ height: 0 }, 133, \"easeOutSine\", afterAnimation);\r\n // } else {\r\n // afterAnimation();\r\n // // $timeout(afterAnimation, 0);\r\n // }\r\n\r\n // document.removeEventListener(\"click\", onDocumentClicked, true);\r\n // // $(\"body\").removeClass(\"is-mobile-keyboard\").css(\"overflow-y\", \"auto\");\r\n // document.body.removeEventListener(\"touchmove\", preventScroll);\r\n // };\r\n\r\n let onDocumentClicked = (e: Event) => {\r\n let $target = $(e.target);\r\n if (\r\n $target.hasClass(\"kb-dropdown__overlay\")\r\n || (\r\n !$target.is(scope.ignoreClickOn) &&\r\n !$target.is($parent) &&\r\n !$.contains($parent[0], e.target as Element) &&\r\n !$target.hasClass(\"kb-dropdown--ignore-click\") &&\r\n !$target.parents(\".kb-dropdown--ignore-click\").length &&\r\n (!scope.ignoreClickOnParent || !$target.parents(scope.ignoreClickOnParent).length)\r\n )\r\n ) {\r\n scope.$apply(() => {\r\n hideDropdown();\r\n if (openIsDefined) {\r\n scope.open = false;\r\n }\r\n });\r\n }\r\n };\r\n\r\n let showDropdown = () => {\r\n if (isVisible) return;\r\n isVisible = true;\r\n\r\n // Workaround for a bug in tether that finds a \"zero element\" in the xr-overlay when in the document.body context, which throws positioning off.\r\n const tetherZeroElem = document.body.querySelector(\".xr-overlay [data-tether-id]\");\r\n if (tetherZeroElem) {\r\n tetherZeroElem.parentElement.removeChild(tetherZeroElem);\r\n }\r\n \r\n createTether();\r\n \r\n let parentWidth = $parent[0].getBoundingClientRect().width;\r\n let maxWidth = scope.width == \"parent\"? parentWidth: (scope.width || \"auto\");\r\n element.css(\"max-width\", maxWidth);\r\n // make the dropdown at least the width of the parent\r\n element.css(\"min-width\", $parent[0].getBoundingClientRect().width);\r\n element.css(\"display\", \"block\");\r\n tether.position();\r\n\r\n scrollToActive();\r\n $parent.addClass(\"is-open\");\r\n element.addClass(\"is-open\");\r\n\r\n document.addEventListener(\"click\", onDocumentClicked, true);\r\n $(document).on(\"touchmove\", preventScroll);\r\n\r\n $timeout(() => tether.position(), 0);\r\n };\r\n\r\n // let showDropdown = () => {\r\n // if (isVisible) return;\r\n // isVisible = true;\r\n // createTether();\r\n // // make the dropdown at least the width of the parent\r\n // element.css(\"min-width\", $parent[0].getBoundingClientRect().width);\r\n // $parent.addClass(\"is-open\");\r\n // element.css(\"display\", \"block\");\r\n\r\n // tether.position();\r\n\r\n // // element.css(\"height\", \"auto\");\r\n // let autoHeight = element.height();\r\n // // if we are attached to the bottom of the element, we don't want the\r\n // // normal height animation, so we just show the dropdown\r\n // let goingDown = !element.hasClass(\"tether-element-attached-bottom\");\r\n\r\n // let afterAnimation = () => {\r\n // element.css(\"height\", \"auto\");\r\n // document.addEventListener(\"click\", onDocumentClicked, true);\r\n // };\r\n // if (scope.animate && goingDown) {\r\n // scrollToActive();\r\n // element.height(0).animate({ height: autoHeight }, 133, \"easeOutSine\", afterAnimation);\r\n // } else { \r\n // timeouts.push($timeout(() => {\r\n // scrollToActive();\r\n // afterAnimation();\r\n // }, 0));\r\n // }\r\n\r\n // // $(\"body\").addClass(\"is-mobile-keyboard\").css(\"overflow-y\", \"hidden\");\r\n // $(document).on(\"touchmove\", preventScroll);\r\n\r\n // };\r\n\r\n let toggleDropdown = (e: JQueryEventObject) => {\r\n\r\n if ($parent.hasClass(\"is-open\")) {\r\n hideDropdown();\r\n } else {\r\n showDropdown();\r\n }\r\n e.stopPropagation();\r\n };\r\n\r\n if (openIsDefined) {\r\n scope.$watch(\"open\", newValue => {\r\n if (newValue) {\r\n showDropdown();\r\n } else {\r\n hideDropdown();\r\n }\r\n });\r\n } else {\r\n $parent.on(\"click.kbdropdown\", toggleDropdown);\r\n }\r\n\r\n scope.$on(\"$destroy\", () => {\r\n timeouts.forEach(t => $timeout.cancel(t));\r\n document.removeEventListener(\"click\", onDocumentClicked, true);\r\n $(document).off(\"touchmove\", preventScroll);\r\n $parent.off(\"click.kbdropdown\");\r\n // remove the dropdown element which is at the bottom of the body thanks to tether\r\n if (tether) tether.destroy();\r\n element.remove();\r\n });\r\n\r\n };\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { keyboard } from \"@tools\";\r\n\r\nexport interface IEditScope extends ng.IScope {\r\n ngModel: string;\r\n enabled: boolean;\r\n\r\n // internal scope properties\r\n _editing: boolean;\r\n _click: () => void;\r\n _blur: () => void;\r\n _keydown: ($event: JQueryEventObject) => void;\r\n}\r\n\r\n@NgComponent({\r\n token: Token.KbEdit,\r\n dependencies: [\r\n Token.$Timeout\r\n ]\r\n})\r\nexport class KbEdit extends Directive {\r\n constructor($timeout: ng.ITimeoutService) {\r\n super();\r\n\r\n this.restrict = \"E\";\r\n this.template = Dirs.component(\"kb-edit\");\r\n this.scope = {\r\n ngModel: \"=\",\r\n enabled: \"=?\"\r\n };\r\n this.replace = true;\r\n\r\n this.link = (scope: IEditScope, element, atts) => {\r\n\r\n let input = $(element).find(\"input\");\r\n\r\n if (typeof scope.enabled == \"undefined\") scope.enabled = true;\r\n\r\n scope.$watch(\"enabled\", newValue => {\r\n if (!newValue) {\r\n scope._editing = false;\r\n input.hide();\r\n }\r\n });\r\n\r\n scope._click = () => {\r\n if (!scope.enabled) return;\r\n scope._editing = true;\r\n input.show();\r\n input.focus();\r\n };\r\n\r\n scope._blur = () => {\r\n scope._editing = false;\r\n input.hide();\r\n };\r\n\r\n scope._keydown = $event => {\r\n $event.stopPropagation();\r\n if ($event.keyCode == keyboard.enter) {\r\n scope._editing = false;\r\n input.hide();\r\n }\r\n };\r\n };\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { KbService } from \"@app/services/kb.service\";\r\n\r\n@NgComponent({\r\n token: Token.KbEllipsis,\r\n dependencies: [\r\n Token.KbService\r\n ]\r\n})\r\nexport class KbEllipsis extends Directive {\r\n constructor(\r\n kbService: KbService\r\n ) {\r\n super();\r\n\r\n this.restrict = \"E\";\r\n this.template = Dirs.component(\"kb-ellipsis\");\r\n this.scope = false;\r\n this.replace = true;\r\n\r\n // this.link = (scope, element, atts) => {\r\n // }\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { IExpanderScope } from \"@app/components/kb-expander/kb-expander.component\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\n\r\nexport interface IExpanderGroupScope extends ng.IScope {\r\n accordion?: boolean;\r\n _expanders?: IExpanderScope[];\r\n}\r\n\r\nexport interface IExpanderGroupController {\r\n scope: IExpanderGroupScope;\r\n registerExpander: (node: IExpanderScope) => void;\r\n expand: (e: IExpanderScope) => void;\r\n}\r\n\r\n@NgComponent({\r\n token: Token.KbExpanderGroup\r\n})\r\nexport class KbExpanderGroup extends Directive {\r\n constructor() {\r\n\r\n super();\r\n\r\n this.replace = false;\r\n this.template = Dirs.component(\"kb-expander-group\");\r\n this.restrict = \"E\";\r\n this.scope = {\r\n accordion: \"=?\"\r\n };\r\n this.transclude = true;\r\n\r\n // // add scope defaults to the compile function\r\n // this.compile = (element, atts: any) => {\r\n // if (!angular.isDefined(atts.accordion)) atts.selectable = \"true\";\r\n // if (!angular.isDefined(atts.expandable)) atts.expandable = \"true\";\r\n // };\r\n\r\n this.controller = [\r\n \"$scope\",\r\n \"$element\",\r\n \"$attrs\",\r\n function (\r\n $scope: IExpanderGroupScope,\r\n $element: ng.IAugmentedJQuery,\r\n $attrs: ng.IAttributes) {\r\n // set the scope of the tree on it's controller so children can access it\r\n this.scope = $scope;\r\n $scope._expanders = [];\r\n\r\n // all child nodes register themselves with the tree to handle selection and accordion functionality\r\n this.registerExpander = (e: IExpanderScope) => {\r\n $scope._expanders.push(e);\r\n let off = e.$on(\"$destroy\", event => {\r\n $scope._expanders.remove(e);\r\n off();\r\n });\r\n if ($scope.accordion) {\r\n for (let expander of $scope._expanders) {\r\n if (expander.expanded) {\r\n updateExpanders(expander);\r\n return;\r\n }\r\n }\r\n }\r\n };\r\n\r\n this.expand = (e: IExpanderScope) => {\r\n if (e.expanded) updateExpanders(e);\r\n };\r\n\r\n let updateExpanders = (activeExpander: IExpanderScope) => {\r\n if ($scope.accordion) {\r\n for (let e of $scope._expanders) {\r\n if (e !== activeExpander) e.expanded = false;\r\n }\r\n }\r\n }; \r\n }];\r\n }\r\n\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { IExpanderGroupController } from \"@app/components/kb-expander/kb-expander-group.component\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\n\r\nexport interface IExpanderScope extends ng.IScope{\r\n expanded?: boolean;\r\n expandedChanged?: any;\r\n invalid?: boolean;\r\n icon?: string;\r\n image?: string;\r\n _toggle: () => void;\r\n}\r\n\r\n@NgComponent({\r\n token: Token.KbExpander,\r\n dependencies: [\r\n Token.$Timeout\r\n ]\r\n})\r\nexport class KbExpander extends Directive {\r\n constructor(\r\n $timeout: ng.ITimeoutService\r\n ) {\r\n super();\r\n\r\n this.restrict = \"E\";\r\n this.template = Dirs.component(\"kb-expander\");\r\n this.transclude = {\r\n \"title\": \"?kbExpanderTitle\",\r\n \"body\": \"kbExpanderBody\"\r\n };\r\n this.scope = {\r\n expanded: \"=?\",\r\n expandedChanged: \"&\",\r\n invalid: \"=?\",\r\n icon: \"@\",\r\n image: \"@\"\r\n };\r\n this.replace = false;\r\n this.require = \"?^^kbExpanderGroup\";\r\n\r\n this.link = (scope: IExpanderScope, element, atts, kbExpanderGroup: IExpanderGroupController) => {\r\n if (kbExpanderGroup) kbExpanderGroup.registerExpander(scope);\r\n scope._toggle = () => {\r\n scope.expanded = !scope.expanded;\r\n }\r\n scope.$watch(\"expanded\", (newVal, oldVal) => {\r\n if (newVal != oldVal) {\r\n if (kbExpanderGroup && scope.expanded) kbExpanderGroup.expand(scope);\r\n if (scope.expandedChanged) scope.expandedChanged();\r\n }\r\n });\r\n };\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { IFormController } from \"@app/components/kb-form/kb-form.component\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { KbService } from \"@app/services/kb.service\";\r\nimport { IAugmentedJQuery } from \"angular\";\r\n\r\nexport interface IFieldController {\r\n scope: IFieldScope;\r\n setFocused: (isFocused: boolean) => void;\r\n setHasValue: (hasValue: boolean) => void;\r\n setShouldFloat: (shouldFloat: boolean) => void;\r\n}\r\n\r\ninterface IFieldScope extends ng.IScope {\r\n // external members\r\n required: string;\r\n label: string;\r\n desc: string;\r\n labelLoc: string;\r\n descLoc: string;\r\n ngDisabled: boolean;\r\n // kbField generall gets it's validation messages from the parent kbForm, however\r\n // it can be overriden by directly supplying validationErrors\r\n validationErrors: string[];\r\n warnings: string[];\r\n runFixThis: Function;\r\n isCheckbox: boolean;\r\n helpMedia: string;\r\n helpUrl: string;\r\n mobileHelpDropdown: boolean;\r\n useZeroPadding: boolean;\r\n\r\n // internal directive members\r\n _checkboxId: string;\r\n _focused: boolean;\r\n _hasValue: boolean;\r\n _runFixThis: Function;\r\n}\r\n\r\n/**\r\n * kbField\r\n * works in tandem with kbForm. Will pull the modelType from kbForm and use it to find localized label\r\n * and description for the field. It will also search it's direct children looking for an ngModel, as it\r\n * needs this info to find the model property name being bound to (also used to find the label and description)\r\n *\r\n * To override the localized label and description, you can directly set the attributes labelLoc and descLockb\r\n * to the name of a localization resource.\r\n *\r\n * If there is no clear way to find the ngModel child, you can set the modelProp attribute to help it find\r\n * the label and desc localizations\r\n *\r\n * The required attribute can be set to true to have a * show up at the end of the label\r\n *\r\n * If the model property is localizeable by the user, set the localize attribute to the model id\r\n * example: \r\n *\r\n *\r\n */\r\n@NgComponent({\r\n token: Token.KbField,\r\n dependencies: [\r\n Token.KbService\r\n ]\r\n})\r\nexport class KbField extends Directive {\r\n constructor(\r\n kbService: KbService\r\n ) {\r\n super();\r\n \r\n this.restrict = \"EA\";\r\n this.template = Dirs.component(\"kb-field\");\r\n this.scope = {\r\n required: \"@\",\r\n label: \"@\",\r\n labelLoc: \"@\",\r\n desc: \"@\",\r\n descLoc: \"@\",\r\n ngDisabled: \"=?\",\r\n validationErrors: \"=?\",\r\n runFixThis: \"&\",\r\n warnings: \"=?\",\r\n fixOptions: \"=?\",\r\n isCheckbox: \"=?\",\r\n helpMedia: \"=?\",\r\n helpUrl: \"=?\",\r\n mobileHelpDropdown: \"=?\",\r\n useZeroPadding: \"=?\"\r\n };\r\n this.replace = true;\r\n this.transclude = true;\r\n this.require = \"^?kbForm\";\r\n\r\n this.compile = (element, atts: any) => {\r\n if (atts.mobileHelpDropdown == null) atts.mobileHelpDropdown = \"true\";\r\n return this.link;\r\n };\r\n\r\n this.controller = [\"$scope\", \"$element\", function($scope: IFieldScope, $element: IAugmentedJQuery) {\r\n this.scope = $scope;\r\n this.setFocused = (focused: boolean) => {\r\n if ($scope._focused !== focused) {\r\n $element.toggleClass(\"kb-field--is-focused\", focused);\r\n }\r\n $scope._focused = focused; \r\n };\r\n this.setHasValue = (hasValue: boolean) => {\r\n if ($scope._hasValue !== hasValue) {\r\n $element.toggleClass(\"kb-field--has-value\", hasValue);\r\n }\r\n $scope._hasValue = hasValue; \r\n };\r\n this.setShouldFloat = (shouldFloat: boolean) => {\r\n $element.toggleClass(\"kb-field--should-float\", shouldFloat);\r\n }\r\n }];\r\n\r\n this.link = (scope: IFieldScope, element, atts: any, kbForm: IFormController) => {\r\n\r\n if (kbForm) { //integration with kbForm\r\n let modelProp: string;\r\n //if in a kbForm, we look in the child input and \r\n // scrape the ng - model from it so we know the property we're connecting to\r\n let $input = element.find(\".kb-field__input *[ng-model]\").first();\r\n if ($input.length > 0) {\r\n let path = $input.attr(\"ng-model\");\r\n modelProp = path.substring(path.lastIndexOf(\".\") + 1);\r\n }\r\n\r\n // if title is specified, then it means it's the name of a loc\r\n let autoLoc: boolean = false; // whether the label/desc is being automatically inferred\r\n if (modelProp && !scope.labelLoc) {\r\n // title was not specified, so we look for a kbForm ancestor that could be providing\r\n // model type information\r\n \r\n if (kbForm && kbForm.scope.modelType && modelProp) {\r\n scope.labelLoc = kbForm.scope.modelType + \"_\" + modelProp + \"_title\";\r\n scope.descLoc = kbForm.scope.modelType + \"_\" + modelProp + \"_desc\";\r\n autoLoc = true;\r\n\r\n // check to see if the loc exists... if not, we can try generic resources\r\n if (!loc[scope.labelLoc.toLowerCase()]) {\r\n scope.labelLoc = \"generic_\" + modelProp + \"_title\";\r\n scope.descLoc = \"generic_\" + modelProp + \"_desc\";\r\n // if the generics don't exist either, then we'll just not have a label\r\n if (!loc[scope.labelLoc.toLowerCase()]) {\r\n scope.labelLoc = \"\";\r\n scope.descLoc = \"\";\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (scope.labelLoc) {\r\n scope.label = kbService.loc(scope.labelLoc);\r\n }\r\n if (scope.descLoc) {\r\n let autoDesc = kbService.loc(scope.descLoc);\r\n scope.desc = (autoLoc && autoDesc == scope.descLoc) ? \"\" : autoDesc;\r\n }\r\n\r\n // validation\r\n // if the validationErrors attribute was set, then we use it\r\n // if not set, then we check for a parentForm's validation property that matches our ngmodel expression\r\n if (!atts.validationErrors) {\r\n scope.$watch(() => {\r\n if (!kbForm.scope.validation) return null;\r\n return kbForm.scope.validation[modelProp];\r\n }, newValue => {\r\n if (newValue) {\r\n scope.validationErrors = [newValue];\r\n } else {\r\n scope.validationErrors ? scope.validationErrors.clear() : scope.validationErrors = [];\r\n }\r\n });\r\n }\r\n } \r\n \r\n\r\n //pass throughs for field controls in a configurator\r\n scope._runFixThis = (f: any) => {\r\n return scope.runFixThis({ fix: f });\r\n };\r\n\r\n // $scope._upload = file => {\r\n // return $scope.upload({ file });\r\n // };\r\n\r\n // $scope._autoCompleteQuery = query => {\r\n // return $scope.autoCompleteQuery({ query, field: $scope.field });\r\n // };\r\n // $scope._autoCompleteGetLabel = value => {\r\n // return $scope.autoCompleteGetLabel({ value, field: $scope.field });\r\n // };\r\n // $scope._translateKbo = property => {\r\n // return $scope.translateKbo({ kbObject: $scope.field, property });\r\n // };\r\n\r\n\r\n \r\n \r\n scope.$on(\"$destroy\", () => {\r\n\r\n });\r\n };\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\nexport interface IFocusScope extends ng.IScope {\r\n \r\n}\r\n\r\n@NgComponent({\r\n token: Token.KbFocus,\r\n dependencies: [\r\n Token.$Timeout\r\n ]\r\n})\r\nexport class KbFocus extends Directive {\r\n constructor(\r\n $timeout: ng.ITimeoutService\r\n ) {\r\n\r\n super();\r\n\r\n this.replace = true;\r\n this.restrict = \"A\";\r\n this.scope = false;\r\n this.link = (scope: IFocusScope, element: ng.IAugmentedJQuery, atts) => {\r\n $timeout(() => {\r\n element[0].focus();\r\n }, 200);\r\n };\r\n \r\n }\r\n\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\n\r\nexport interface IFormController {\r\n scope: IFormScope;\r\n}\r\n\r\nexport interface IFormScope extends ng.IScope {\r\n modelType: string;\r\n validation: any;\r\n ngDisabled: boolean;\r\n}\r\n\r\n@NgComponent({\r\n token: Token.KbForm,\r\n dependencies: [\r\n ]\r\n})\r\nexport class KbForm extends Directive {\r\n constructor() {\r\n super();\r\n\r\n this.replace = true;\r\n this.template = Dirs.component(\"kb-form\");\r\n this.restrict = \"E\";\r\n this.scope = {\r\n modelType: \"@\",\r\n validation: \"=\",\r\n ngDisabled: \"=?\"\r\n };\r\n this.transclude = true;\r\n\r\n this.controller = [\"$scope\", \"$element\", function($scope: IFormScope, $element) {\r\n this.scope = $scope;\r\n }];\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { KbService } from \"@app/services/kb.service\";\r\n\r\n@NgComponent({\r\n token: Token.KbIcon,\r\n dependencies: [\r\n Token.KbService\r\n ]\r\n})\r\nexport class KbIcon extends Directive {\r\n constructor(\r\n private kbService: KbService\r\n ) {\r\n super();\r\n\r\n this.restrict = \"E\";\r\n this.template = Dirs.component(\"kb-icon\");\r\n this.scope = {\r\n icon: \"@\",\r\n label: \"@\"\r\n };\r\n this.replace = true;\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\n/**\r\n * A performance driven directive that does the following:\r\n * * will not render the html it is placed on until the kb-if evaluates to truthy (like ng-if)\r\n * * will NOT destroy the html when kb-if thereafter evaluates to false. Instead, it will\r\n * hide the html like ng-show would, but also suspend all the watchers on this element and any children.\r\n * \r\n * Uses the feature described here: https://github.com/angular/angular.js/pull/16308\r\n */\r\n@NgComponent({\r\n token: Token.KbIf,\r\n dependencies: [\r\n Token.$Animate\r\n ]\r\n})\r\nexport class KbIf extends Directive {\r\n constructor(\r\n $animate: ng.animate.IAnimateService\r\n ) {\r\n super();\r\n this.watchAtt = \"kbIf\";\r\n this.restrict = \"A\";\r\n this.priority = 600;\r\n this.transclude = \"element\";\r\n this.terminal = true;\r\n this.$$tlb = true;\r\n this.link = (scope, element: JQuery, atts, ctrl, $transclude) => {\r\n let innerScope;\r\n let innerElement; \r\n\r\n let hide = () => {\r\n $animate.addClass(innerElement, \"ng-hide\", {\r\n tempClasses: \"ng-hide-animate\"\r\n } as any);\r\n };\r\n let show = () => {\r\n $animate.removeClass(innerElement, \"ng-hide\", {\r\n tempClasses: \"ng-hide-animate\"\r\n } as any);\r\n };\r\n scope.$watch(atts[this.watchAtt], (value, oVal) => {\r\n\r\n // $animate[value ? 'removeClass' : 'addClass'](innerElement, NG_HIDE_CLASS, {\r\n // tempClasses: NG_HIDE_IN_PROGRESS_CLASS\r\n // });\r\n\r\n if (value) {\r\n if (!innerElement) {\r\n // Add the transcluded content after the transclusion comment placeholder \r\n $transclude((el, sc) => {\r\n element.after(el);\r\n innerElement = el;\r\n innerScope = sc;\r\n innerScope.$resume();\r\n $animate.enter(el, element.parent(), element);\r\n innerElement.removeClass(\"ng-hide\");\r\n });\r\n } else {\r\n innerScope.$resume();\r\n show();\r\n } \r\n } else {\r\n if (innerElement) {\r\n if (this.hideDelay) {\r\n setTimeout(() => {\r\n hide();\r\n }, this.hideDelay)\r\n } else {\r\n hide();\r\n } \r\n // Before suspending, the scope should digest one more time to allow updates (e.g. initial watch)\r\n (scope as any).$$postDigest(() => {\r\n innerScope.$suspend();\r\n });\r\n } \r\n }\r\n });\r\n };\r\n }\r\n\r\n public hideDelay: number;\r\n public watchAtt: string;\r\n}\r\n\r\n","import { KbIf } from \"@app/components/kb-if/kb-if.component\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\n/**\r\n * A version of kbIf that delays the adding of the ng-hide once the value resolves to false to\r\n * give animations a chance to finish.\r\n */\r\n@NgComponent({\r\n token: Token.KbIfDelay,\r\n dependencies: [\r\n Token.$Animate\r\n ]\r\n})\r\nexport class KbIfDelay extends KbIf {\r\n constructor(\r\n $animate: ng.animate.IAnimateService\r\n ) {\r\n super($animate);\r\n this.watchAtt = \"kbIfDelay\";\r\n this.hideDelay = 300;\r\n }\r\n}","import { IInputScope, KbInput } from \"@app/components/kb-input/kb-input.component\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { SearchUtils, Utils } from \"@tools\";\r\nimport * as angular from \"angular\";\r\n\r\nexport interface IMultiSelectScope extends IInputScope {\r\n // external members\r\n ngModel: any[];\r\n source: any[];\r\n\r\n /**\r\n * 'objects' or 'values'. 'objects' is the default\r\n * In objects mode, when a source item is selected, the whole object will be added to the ngModel array.\r\n * In values mode, only the value of the source item will be added to the ngModel array.\r\n * NOTE: the mode is overriden when addItem delegate is used. \r\n * AddItem gives you control over exactly how to add the item.\r\n */\r\n mode: string;\r\n /**\r\n * leave valueField empty to treat the whole option item as the value\r\n */\r\n valueField: string;\r\n labelField: string;\r\n\r\n headerTemplate: string;\r\n allowDeleteInHeader: boolean;\r\n itemIsSelectable: (item: any) => boolean;\r\n /**\r\n * custom data passed in so that header templates can access things in the outer scope\r\n */\r\n data: any;\r\n /**\r\n * Take manual control of adding an item.\r\n */\r\n addItem: (sourceItem: any) => void;\r\n /**\r\n * take manual control of the removal of an item\r\n */\r\n removeItem: (item: any) => void;\r\n ngDisabled: boolean;\r\n itemStyle: any;\r\n mobileDropdown: boolean;\r\n\r\n // internal directive members\r\n _selectedItems: any[];\r\n /** the option currently highlighted in the dropdown (not necessarily the same as the selectedOption) */\r\n _activeIndex: number;\r\n _select: (item: any) => void;\r\n _click: (e: ng.IAngularEvent) => void;\r\n _dropdownOpen: boolean;\r\n _isEnabled: () => boolean;\r\n _itemDeleteBtnClick: (e: ng.IAngularEvent, item: any) => void;\r\n _delete: (item: any) => void;\r\n _isActive: (index) => boolean;\r\n _selectedMap: boolean[];\r\n _getItemLabel: (item: any) => string;\r\n _id: string;\r\n\r\n _binding: { query: string };\r\n _filteredSource: any[];\r\n _queryChange: (e: ng.IAngularEvent) => void;\r\n _queryKeydown: (e: JQueryEventObject) => void;\r\n _itemClick: (e: JQueryEventObject, item: any) => void;\r\n _itemMousedown: (e: JQueryEventObject) => void;\r\n _itemIsSelectable: (item: any) => boolean;\r\n}\r\n\r\n@NgComponent({\r\n token: Token.KbMultiSelect,\r\n dependencies: [\r\n Token.$Timeout,\r\n Token.$Window,\r\n ]\r\n})\r\nexport class KbMultiSelect extends KbInput {\r\n constructor(\r\n $timeout: ng.ITimeoutService,\r\n $window: ng.IWindowService\r\n ) {\r\n super($timeout);\r\n\r\n this.template = Dirs.component(\"kb-multi-select\");\r\n this.scope = Utils.extend(this.scope, {\r\n source: \"=\",\r\n valueField: \"@\",\r\n labelField: \"@\",\r\n headerTemplate: \"@\",\r\n data: \"=?\",\r\n addItem: \"&\",\r\n removeItem: \"&\",\r\n mode: \"@\",\r\n itemStyle: \"=?\",\r\n allowDeleteInHeader: \"=?\",\r\n itemIsSelectable: \"&\",\r\n mobileDropdown: \"=?\"\r\n });\r\n this.transclude = true;\r\n\r\n this.compile = (element, atts: any) => {\r\n if (angular.isUndefined(atts.mode)) {\r\n atts.mode = \"objects\";\r\n }\r\n if (angular.isUndefined(atts.allowDeleteInHeader)) {\r\n atts.allowDeleteInHeader = \"true\";\r\n }\r\n if (atts.mobileDropdown == null) atts.mobileDropdown = \"true\";\r\n\r\n return this.link;\r\n };\r\n this.link = (s, e, a, c) => this.kbMultiSelectLinkFn(s as IMultiSelectScope, e, a, c, true);\r\n }\r\n public kbMultiSelectLinkFn(scope: IMultiSelectScope, element: JQuery, atts: any, controllers: any[], shouldFloat: boolean = true) {\r\n this.kbInputLinkFn(scope, element, atts, controllers, shouldFloat);\r\n let ngModelCtrl = controllers[0] as ng.INgModelController;\r\n\r\n scope._dropdownOpen = false;\r\n scope._selectedItems = [];\r\n scope._selectedMap = [];\r\n scope._binding = { query: \"\" };\r\n let input = element.find(\"input\");\r\n scope._id = Utils.shortId();\r\n\r\n scope._isEnabled = () => {\r\n return !scope.ngDisabled;\r\n };\r\n\r\n let getItemValue = (item: any) => {\r\n if (item == null) return null;\r\n return scope.valueField ? item[scope.valueField] : item;\r\n };\r\n\r\n scope._getItemLabel = (item: any): string => {\r\n if (scope.labelField && item[scope.labelField]) {\r\n return item[scope.labelField];\r\n } else if (scope.valueField) {\r\n return item[scope.valueField];\r\n } else {\r\n return item;\r\n }\r\n };\r\n\r\n let updateSelected = () => {\r\n scope._selectedItems.clear();\r\n // set all options to visible\r\n scope._selectedMap.clear();\r\n if (scope.source) scope.source.forEach(item => scope._selectedMap.push(false));\r\n\r\n if (ngModelCtrl.$viewValue) {\r\n for (let item of ngModelCtrl.$viewValue) {\r\n let itemValue = item;\r\n if (scope.mode == \"objects\") {\r\n itemValue = getItemValue(item);\r\n }\r\n\r\n if (scope.source) {\r\n for (let i = 0; i < scope.source.length; i++) {\r\n let sourceItem = scope.source[i];\r\n if (getItemValue(sourceItem) == itemValue) {\r\n scope._selectedItems.push(sourceItem);\r\n // hide the option since it's selected\r\n scope._selectedMap[i] = true;\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n };\r\n\r\n // let showDropdown = () => {\r\n // scope._dropdownOpen = true;\r\n // // on mobile the filter input will kick off the keyboard, which we don't necessarily want. \r\n // // The problem is worse on IOS because of focus restrictions\r\n // if ($window.innerWidth >= Utils.MOBILE_WIDTH && !Utils.isIos()) {\r\n // $timeout(() => input.focus());\r\n // }\r\n // };\r\n\r\n // let hideDropdown = () => {\r\n // scope._dropdownOpen = false;\r\n // scope._binding.query = null;\r\n // updateFilteredSource();\r\n // };\r\n // let toggleDropdown = () => {\r\n // scope._dropdownOpen ? hideDropdown() : showDropdown();\r\n // };\r\n\r\n // options might be added after the ngModel is set by the consumer, so\r\n // we need to refind the selected option \r\n scope.$watchCollection(\"source\", () => {\r\n updateSelected();\r\n updateFilteredSource();\r\n });\r\n\r\n scope.$watchCollection(\"ngModel\", () => {\r\n // ngModel watches by reference, which doesn't work well for arrays\r\n updateSelected();\r\n });\r\n\r\n ngModelCtrl.$render = () => {\r\n updateSelected();\r\n };\r\n\r\n scope._itemMousedown = (e) => {\r\n e.preventDefault(); // so we don't lose focus\r\n }\r\n scope._itemClick = (e, item) => {\r\n e.preventDefault(); \r\n scope._select(item);\r\n };\r\n\r\n scope._itemIsSelectable = (item) => {\r\n if (atts.itemIsSelectable) {\r\n return scope.itemIsSelectable({ item });\r\n }\r\n return true;\r\n }\r\n \r\n scope._select = (sourceItem) => {\r\n if (scope._isEnabled() && scope._itemIsSelectable(sourceItem)) {\r\n if (atts.addItem) {\r\n scope.addItem({ sourceItem });\r\n } else {\r\n if (isSelected(sourceItem)) {\r\n scope._delete(sourceItem);\r\n } else {\r\n let viewValue = ngModelCtrl.$viewValue as any[];\r\n if (scope.mode == \"objects\") { \r\n ngModelCtrl.$setViewValue(viewValue.concat([sourceItem])); // $viewValue.push(sourceItem);\r\n } else {\r\n ngModelCtrl.$setViewValue(viewValue.concat([getItemValue(sourceItem)]));\r\n }\r\n }\r\n }\r\n //updateSelected(); don't need to call because the watch on ngModel picks up the change\r\n //scope.ngChange();\r\n // moveDown();\r\n \r\n }\r\n };\r\n\r\n scope._isActive = index => {\r\n return index === scope._activeIndex;\r\n };\r\n\r\n let updateFilteredSource = () => {\r\n if (!scope._binding.query) {\r\n scope._filteredSource = scope.source;\r\n } else {\r\n scope._filteredSource = SearchUtils.search(\r\n scope._binding.query,\r\n scope.source,\r\n o => scope._getItemLabel(o),\r\n 10000\r\n );\r\n scope._activeIndex = -1;\r\n }\r\n };\r\n\r\n scope._queryChange = e => {\r\n updateFilteredSource();\r\n };\r\n\r\n scope._queryKeydown = e => {\r\n if (e.which == 38) {\r\n moveUp();\r\n e.stopPropagation();\r\n }\r\n if (e.which == 40) {\r\n moveDown();\r\n e.stopPropagation();\r\n }\r\n if (e.which === 13) {\r\n enter();\r\n e.stopPropagation();\r\n }\r\n if (e.which === 9) {\r\n tab();\r\n if (scope._dropdownOpen) {\r\n e.stopPropagation();\r\n e.preventDefault();\r\n }\r\n }\r\n };\r\n\r\n scope._click = e => {\r\n if (scope._isEnabled()) {\r\n scope._activeIndex = -1;\r\n scope._dropdownOpen = !scope._dropdownOpen;\r\n }\r\n };\r\n\r\n scope._itemDeleteBtnClick = (e, item) => {\r\n scope._delete(item);\r\n e.stopPropagation();\r\n };\r\n\r\n scope._delete = (item) => {\r\n if (scope._isEnabled()) {\r\n if (atts.removeItem) {\r\n scope.removeItem({ item });\r\n } else {\r\n let itemValue = getItemValue(item);\r\n // the normal array.remove compares values strictly (with ===), \r\n // but we need == in this case because of possible string / number mismatch\r\n for (let i = ngModelCtrl.$viewValue.length - 1; i >= 0; i--) {\r\n let ngModelValue = ngModelCtrl.$viewValue[i];\r\n if (scope.mode == \"objects\") {\r\n ngModelValue = getItemValue(ngModelValue);\r\n }\r\n if (ngModelValue == itemValue) {\r\n let viewValue = ngModelCtrl.$viewValue as any[];\r\n let newVal = [...viewValue];\r\n newVal.splice(i, 1);\r\n ngModelCtrl.$setViewValue(newVal);\r\n break;\r\n }\r\n }\r\n }\r\n //updateSelected(); don't need to call because the watch on ngModel picks up the change\r\n // scope.ngChange();\r\n }\r\n };\r\n\r\n let isSelected = sourceItem => {\r\n let optionVal = getItemValue(sourceItem);\r\n for (let selectedItem of scope._selectedItems) {\r\n if (optionVal === getItemValue(selectedItem)) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n };\r\n let moveUp = () => {\r\n if (scope._dropdownOpen) {\r\n let newIndex = scope._activeIndex - 1;\r\n if (newIndex >= 0) {\r\n scope._activeIndex = newIndex;\r\n }\r\n }\r\n };\r\n\r\n let moveDown = () => {\r\n scope._dropdownOpen = true;\r\n let newIndex = scope._activeIndex + 1;\r\n if (newIndex < scope._filteredSource.length) {\r\n scope._activeIndex = newIndex;\r\n }\r\n };\r\n\r\n let enter = () => {\r\n if (scope._dropdownOpen) {\r\n if (scope._filteredSource.length && scope._activeIndex > -1) {\r\n scope._select(scope.source[scope._activeIndex]);\r\n }\r\n } else {\r\n scope._dropdownOpen = true;\r\n }\r\n };\r\n\r\n let tab = () => {\r\n if (scope._dropdownOpen) {\r\n if (scope._filteredSource.length && scope._activeIndex > -1) {\r\n scope._select(scope.source[scope._activeIndex]);\r\n scope._dropdownOpen = false;\r\n }\r\n }\r\n };\r\n\r\n // bind keyboard events: arrows up(38) / down(40), enter(13) and tab(9), esc(27)\r\n element.on(\"keydown\", (e: JQuery.Event) => {\r\n if (e.key == 'ArrowUp') {\r\n e.preventDefault();\r\n scope.$apply(() => {\r\n moveUp();\r\n });\r\n }\r\n if (e.key == 'ArrowDown') {\r\n e.preventDefault();\r\n scope.$apply(() => {\r\n moveDown();\r\n });\r\n }\r\n if (e.key == 'Enter') {\r\n scope.$apply(() => {\r\n e.preventDefault();\r\n enter();\r\n });\r\n }\r\n if (e.key == 'Tab') {\r\n scope.$apply(() => {\r\n if (scope._dropdownOpen) {\r\n e.stopPropagation();\r\n e.preventDefault();\r\n }\r\n tab();\r\n });\r\n }\r\n if (e.key == 'Escape') {\r\n e.preventDefault();\r\n element.trigger('blur');\r\n scope.$apply(() => {\r\n scope._dropdownOpen = false;\r\n e.stopPropagation();\r\n });\r\n }\r\n });\r\n\r\n scope.$on(\"$destroy\", () => {\r\n element.off();\r\n });\r\n }\r\n}\r\n","import { eOptionLayout } from \"@models\";\r\nimport { Utils } from \"@tools\";\r\n\r\nexport interface IImageSelectHelperScope extends ng.IScope{\r\n optionLayout?: string;\r\n}\r\n\r\nexport class ImageSelectHelper {\r\n constructor(\r\n private $window: ng.IWindowService,\r\n private $timeout: ng.ITimeoutService,\r\n private scope: IImageSelectHelperScope,\r\n private element: JQuery\r\n ) {\r\n \r\n let windowResize = Utils.debounce(() => {\r\n //if we are in a mode of scroll, then we need to find a margin between items that leaves an option\r\n //halfway out of view to be clear there are more items to scroll horizontally to.\r\n\r\n if (scope.optionLayout == eOptionLayout.scroll) {\r\n\r\n //make sure there are enough items to scroll\r\n let minMargin = 4;\r\n let play = .05;\r\n let minPlayRange = .5 - play;\r\n let maxPlayRange = .5 + play;\r\n let $items = element.find(\".kb-option\");\r\n let $firstItem = $items.length ? $items[0] : null;\r\n if ($firstItem) {\r\n let itemWidth = $firstItem.offsetWidth;\r\n let itemAndMargin = itemWidth + minMargin;\r\n let elWidth = element.innerWidth();\r\n\r\n //make sure there are enough items that we should be scrolling\r\n if (elWidth < (itemAndMargin * $items.length)) {\r\n //find the number of visible items with min margin\r\n let n = elWidth / itemAndMargin;\r\n //now round up to the nearest half\r\n let remainder = n % 1;\r\n if (remainder < minPlayRange || remainder > maxPlayRange) {\r\n let nModifier = remainder < minPlayRange ? -remainder - .5 : .5 - remainder;\r\n let idealN = n + nModifier;\r\n let idealMargin = (elWidth - (itemWidth * idealN)) / (idealN - .5);\r\n $items.css(\"margin-right\", idealMargin);\r\n } else {\r\n //do nothing... we are close enough\r\n $items.css(\"margin-right\", minMargin);\r\n }\r\n }\r\n }\r\n }\r\n }, 100);\r\n\r\n $($window).on(\"resize\", windowResize);\r\n $timeout(() => {\r\n windowResize();\r\n }, 0);\r\n\r\n scope.$watch(\"optionLayout\", (newVal, oldVal) => {\r\n element.removeClass(\"kb-image-select--\" + (oldVal || eOptionLayout.wrap));\r\n element.addClass(\"kb-image-select--\" + (newVal || eOptionLayout.wrap));\r\n windowResize();\r\n });\r\n\r\n scope.$on(\"$destroy\", () => {\r\n element.off();\r\n $($window).off(\"resize\", windowResize);\r\n });\r\n }\r\n}\r\n","import { IMultiSelectScope, KbMultiSelect } from \"@app/components/kb-multi-select/kb-multi-select.component\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { ImageSelectHelper } from \"@app/helpers/image-select.helper\";\r\nimport { Utils } from \"@tools\";\r\n\r\nexport interface IImageMultiSelectScope extends IMultiSelectScope {\r\n optionLayout?: string;\r\n}\r\n\r\n@NgComponent({\r\n token: Token.KbImageMultiSelect,\r\n dependencies: [\r\n Token.$Timeout,\r\n Token.$Window,\r\n ]\r\n})\r\nexport class KbImageMultiSelect extends KbMultiSelect {\r\n constructor(\r\n $timeout: ng.ITimeoutService,\r\n $window: ng.IWindowService\r\n ) {\r\n super($timeout, $window);\r\n this.scope = Utils.extend(this.scope, {\r\n optionLayout: \"=?\"\r\n });\r\n this.template = Dirs.component(\"kb-image-multi-select\");\r\n\r\n this.link = (scope: IImageMultiSelectScope, element: ng.IAugmentedJQuery, atts: ng.IAttributes, controllers: any[]) => {\r\n this.kbMultiSelectLinkFn(scope, element, atts, controllers, false);\r\n let helper = new ImageSelectHelper($window, $timeout, scope, element);\r\n\r\n };\r\n }\r\n}\r\n","import { IInputScope, KbInput } from \"@app/components/kb-input/kb-input.component\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { ImageSelectHelper } from \"@app/helpers/image-select.helper\";\r\nimport { eOptionLayout } from \"@models\";\r\nimport { eScrollMode, Utils } from \"@tools\";\r\n\r\nexport interface IImageSelectScope extends IInputScope {\r\n // external members\r\n source: any[];\r\n data: any; // custom data that can be passed in and accessed by the transcluded content for the select items\r\n valueField: string;\r\n labelField: string;\r\n itemStyle: any;\r\n optionLayout: string;\r\n\r\n // internal directive members\r\n _selectedItem: any;\r\n _select: (item: any) => void;\r\n _helpClick: (e: ng.IAngularEvent) => void;\r\n\r\n _paged: boolean;\r\n _scrollNext: () => void;\r\n _scrollPrev: () => void;\r\n _pageNextVisible: boolean;\r\n _pagePrevVisible: boolean;\r\n}\r\n\r\nexport interface IImageSelectController {\r\n scope: IImageSelectScope;\r\n}\r\n\r\n@NgComponent({\r\n token: Token.KbImageSelect,\r\n dependencies: [\r\n Token.$Timeout,\r\n Token.$Window\r\n ]\r\n})\r\nexport class KbImageSelect extends KbInput {\r\n constructor($timeout: ng.ITimeoutService, $window: ng.IWindowService) {\r\n super($timeout);\r\n\r\n this.template = Dirs.component(\"kb-image-select\");\r\n this.scope = Utils.extend(this.scope, {\r\n source: \"=\",\r\n data: \"=?\",\r\n valueField: \"@\",\r\n labelField: \"@\",\r\n itemStyle: \"=?\",\r\n optionLayout: \"=?\"\r\n });\r\n this.transclude = true;\r\n\r\n this.link = (scope: IImageSelectScope, element: JQuery, atts, controllers: any[]) => {\r\n this.kbInputLinkFn(scope, element, atts, controllers, false);\r\n let helper = new ImageSelectHelper($window, $timeout, scope, element);\r\n\r\n let ngModel = controllers[0] as ng.INgModelController;\r\n\r\n let getItemValue = (item: any) => {\r\n if (item === null || item === undefined) return null;\r\n return scope.valueField ? item[scope.valueField] : item;\r\n };\r\n let getItemLabel = (item: any): string => {\r\n if (scope.labelField && item[scope.labelField]) {\r\n return item[scope.labelField];\r\n } else if (scope.valueField) {\r\n return item[scope.valueField];\r\n } else {\r\n return item;\r\n }\r\n };\r\n\r\n let isEnabled = () => {\r\n return !scope.ngDisabled;\r\n };\r\n\r\n let updateSelected = () => {\r\n let selected = null;\r\n if (scope.source) {\r\n for (let item of scope.source) {\r\n item.$selected = false;\r\n if (getItemValue(item) == ngModel.$viewValue) {\r\n selected = item;\r\n item.$selected = true;\r\n }\r\n }\r\n }\r\n scope._selectedItem = selected;\r\n };\r\n \r\n // options might be added after the ngModel is set by the consumer, so\r\n // we need to refind the selected option \r\n scope.$watchCollection(\"source\", () => {\r\n updateSelected();\r\n });\r\n\r\n ngModel.$render = () => {\r\n updateSelected();\r\n };\r\n\r\n scope._select = (item: any) => {\r\n if (isEnabled()) {\r\n ngModel.$setViewValue(getItemValue(item));\r\n scope._selectedItem = item;\r\n for (let item of scope.source) item.$selected = false;\r\n item.$selected = true;\r\n }\r\n };\r\n\r\n scope._helpClick = e => {\r\n e.stopPropagation();\r\n };\r\n\r\n let moveUp = () => {\r\n if (scope.source && scope._selectedItem) {\r\n let curIndex = scope.source.indexOf(scope._selectedItem);\r\n let newIndex = curIndex - 1;\r\n if (newIndex >= 0) scope._select(scope.source[newIndex]);\r\n } else if (scope.source && scope.source.length) {\r\n scope._select(scope.source[0]);\r\n }\r\n };\r\n\r\n let moveDown = () => {\r\n if (scope.source && scope._selectedItem) {\r\n let curIndex = scope.source.indexOf(scope._selectedItem);\r\n let newIndex = curIndex + 1;\r\n if (newIndex < scope.source.length) scope._select(scope.source[newIndex]);\r\n } else if (scope.source && scope.source.length) {\r\n scope._select(scope.source[0]);\r\n }\r\n };\r\n \r\n let scrollSelectedIntoView = () => {\r\n if (scope.optionLayout == eOptionLayout.scroll) {\r\n $timeout(() => {\r\n let $selected = element.find(\".kb-option.selected\");\r\n let selectedElem = $selected.length ? $selected[0] : null;\r\n if (selectedElem) {\r\n Utils.scrollIntoView({\r\n elem: selectedElem,\r\n mode: eScrollMode.nearest,\r\n horizontal: true,\r\n animate: true,\r\n nearestEndPadding: parseInt(selectedElem.style.marginRight) + selectedElem.offsetWidth/2\r\n });\r\n }\r\n });\r\n }\r\n }\r\n\r\n scope.$watch(\"_selectedItem\", () => {\r\n scrollSelectedIntoView();\r\n });\r\n\r\n \r\n // bind keyboard events: arrows up(38) / down(40), enter(13) and tab(9), esc(27)\r\n element.on(\"keydown\", (e: JQueryEventObject) => {\r\n if (e.key == 'ArrowLeft' || e.key == 'ArrowUp') {\r\n e.preventDefault();\r\n scope.$apply(() => {\r\n moveUp();\r\n });\r\n }\r\n if (e.key == 'ArrowRight' || e.key == 'ArrowDown') {\r\n e.preventDefault();\r\n scope.$apply(() => {\r\n moveDown();\r\n });\r\n }\r\n if (e.key == 'Escape') {\r\n element.trigger('blur');\r\n }\r\n });\r\n\r\n scope.$on(\"$destroy\", () => {\r\n element.off();\r\n // $($window).off(\"resize\", windowResize);\r\n });\r\n\r\n };\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport * as angular from \"angular\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\n/**\r\n * Creates a new scope for ng-include along with being able to set variables on the new scope\r\n */\r\n@NgComponent({\r\n token: Token.KbInclude,\r\n dependencies: [\r\n Token.$TemplateRequest,\r\n Token.$Compile\r\n ]\r\n})\r\nexport class KbInclude extends Directive {\r\n constructor(\r\n $templateRequest: ng.ITemplateRequestService,\r\n $compile: ng.ICompileService\r\n ) {\r\n super();\r\n\r\n this.restrict = \"A\";\r\n this.link = (scope, element: JQuery, atts: any) => {\r\n let templateUrl = scope.$eval(atts.kbInclude);\r\n\r\n $templateRequest(templateUrl, true).then(response => {\r\n let $template = angular.element(response);\r\n // compile the template\r\n let compiled = $compile($template);\r\n // append it to the label\r\n element.replaceWith($template);\r\n // now link it to the parent scope(we don't want this scope because it's an isolate scope)\r\n compiled(scope);\r\n });\r\n };\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { IRootScope } from \"@models\";\r\nimport { Utils } from \"@tools\";\r\nimport * as angular from \"angular\";\r\n\r\n@NgComponent({\r\n token: Token.KbInfiniteScroll,\r\n dependencies: [\r\n Token.$RootScope,\r\n Token.$Window,\r\n Token.$Timeout,\r\n Token.$Compile,\r\n Token.PromiseTracker,\r\n Token.$Q,\r\n ]\r\n})\r\nexport class KbInfiniteScroll extends Directive {\r\n constructor(\r\n private $rootScope: IRootScope,\r\n $window: ng.IWindowService,\r\n $timeout: ng.ITimeoutService,\r\n $compile: ng.ICompileService,\r\n promiseTracker: ng.IPromiseTracker,\r\n $q: ng.IQService\r\n ) {\r\n super();\r\n\r\n this.restrict = \"A\";\r\n this.replace = false;\r\n this.scope = false;\r\n\r\n this.link = (scope: any, element, atts: any) => {\r\n // var checkWhenEnabled: boolean;\r\n let scrollDistance: number;\r\n // var scrollEnabled: boolean;\r\n\r\n let window = angular.element($window);\r\n\r\n let $parent: angular.IAugmentedJQuery;\r\n let $child: angular.IAugmentedJQuery;\r\n if (angular.isDefined(atts.kbInfiniteScrollParent)) {\r\n $parent = angular.element(atts.kbInfiniteScrollParent);\r\n //if we are inside a directive, then the element might not be in the DOM yet,\r\n //so we search for it in the directive element chain\r\n if (!$parent.length) {\r\n $parent = this.findDirectiveElement(element, atts.kbInfiniteScrollParent);\r\n }\r\n } else {\r\n $parent = $window as any;\r\n }\r\n if (angular.isDefined(atts.kbInfiniteScrollChild)) {\r\n $child = angular.element(atts.kbInfiniteScrollChild);\r\n //if we are inside a directive, then the element might not be in the DOM yet,\r\n //so we search for it in the directive element chain\r\n if (!$child.length) {\r\n $child = this.findDirectiveElement(element, atts.kbInfiniteScrollChild);\r\n }\r\n } else {\r\n $child = element;\r\n }\r\n\r\n let isHorizontal: boolean = false;\r\n if (angular.isDefined(atts.kbInfiniteScrollOrientation)) {\r\n if (atts.kbInfiniteScrollOrientation.toLowerCase() == \"horizontal\") {\r\n isHorizontal = true;\r\n }\r\n }\r\n\r\n let template;\r\n if (isHorizontal) {\r\n template = `\r\n
\r\n
`;\r\n } else {\r\n template = `\r\n
\r\n
`;\r\n }\r\n let $template = $(template);\r\n let spinner = ``;\r\n\r\n $template.append(spinner);\r\n $template = $compile($template)(scope);\r\n element.append($template);\r\n\r\n scrollDistance = 0;\r\n if (atts.kbInfiniteScrollDistance) {\r\n scope.$watch(atts.kbInfiniteScrollDistance, value => {\r\n return scrollDistance = parseFloat(value);\r\n });\r\n }\r\n\r\n let busy = false;\r\n let handler = Utils.debounce(() => {\r\n if (busy) return;\r\n busy = true;\r\n\r\n let shouldScroll = false;\r\n\r\n if (isHorizontal) {\r\n let parentWidth = $parent[0].clientWidth;\r\n let portalRight = parentWidth + $parent[0].scrollLeft;\r\n let remaining = $child[0].clientWidth - portalRight;\r\n shouldScroll = remaining <= parentWidth * scrollDistance;\r\n } else {\r\n let parentHeight = $parent[0].clientHeight;\r\n let portalBottom = parentHeight + $parent[0].scrollTop;\r\n let remaining = $child[0].clientHeight - portalBottom;\r\n shouldScroll = remaining <= parentHeight * scrollDistance;\r\n }\r\n\r\n return $q.when(shouldScroll && scope.$eval(atts.kbInfiniteScroll)).then(() => {\r\n busy = false;\r\n });\r\n }, 10);\r\n\r\n let onMousewheel = (e: WheelEvent) => {\r\n if (e.deltaY === 1) {\r\n e.preventDefault();\r\n }\r\n };\r\n\r\n $parent[0].addEventListener(\"scroll\", handler);\r\n $parent[0].addEventListener(\"mousewheel\", onMousewheel) //need the mousewheel event for a bug in chrome: https://stackoverflow.com/a/47684257/709968\r\n //$parent.on(\"scroll\", handler);\r\n scope.$on(\"$destroy\", () => {\r\n $parent[0].removeEventListener(\"scroll\", handler);\r\n $parent[0].removeEventListener(\"mousewheel\", onMousewheel);\r\n //return $parent.off(\"scroll\", handler);\r\n });\r\n return $timeout((() => {\r\n if (atts.kbInfiniteScrollImmediateCheck) {\r\n if (scope.$eval(atts.kbInfiniteScrollImmediateCheck)) {\r\n return handler();\r\n }\r\n } else {\r\n return handler();\r\n }\r\n }), 0);\r\n\r\n };\r\n\r\n }\r\n\r\n public findDirectiveElement(directiveElement: ng.IAugmentedJQuery, selector: string) {\r\n //if we are inside a directive, then the element might not be in the DOM yet,\r\n //so we search for it in the directive element chain\r\n let p = directiveElement;\r\n while (p.parent().length) {\r\n p = p.parent();\r\n }\r\n return p.find(selector).addBack(selector);\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\n\r\nexport interface ILabelScope extends ng.IScope {\r\n invalid: boolean;\r\n icon: string;\r\n image: string;\r\n imageWhenSelected: string;\r\n selected: boolean;\r\n\r\n}\r\n\r\n@NgComponent({\r\n token: Token.KbLabel\r\n})\r\nexport class KbLabel extends Directive {\r\n constructor() {\r\n super();\r\n\r\n this.replace = true;\r\n this.template = Dirs.component(\"kb-label\");\r\n this.restrict = \"E\";\r\n this.scope = {\r\n invalid: \"=?\",\r\n icon: \"@\",\r\n image: \"@\",\r\n imageWhenSelected: \"@\",\r\n selected: \"=?\",\r\n backgroundColor: \"=?\",\r\n textColor: \"=?\"\r\n };\r\n this.transclude = true;\r\n\r\n this.link = (scope: ILabelScope, element, atts: any) => {\r\n \r\n };\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport * as angular from \"angular\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { IListController, IListScope } from \"@app/components/kb-list/kb-list.component\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\nexport interface IListItemScope extends ng.IScope {\r\n item: any; // the data item that represents the node\r\n selectable: boolean; // controls whether the item is selectable\r\n image: string; // the relative path to an image in the media folder\r\n icon: string; // the name of a kbicon\r\n onDelete: (item: any) => void; // gets called when the delete button or key is pressed\r\n onDoubleClick: () => void;\r\n deletable: boolean; // will add a delete button that when pressed will call onDelete()\r\n childTemplate: string;\r\n\r\n // internal \r\n _itemClick: ($event: ng.IAngularEvent) => void;\r\n _itemDoubleClick: ($event: ng.IAngularEvent) => void;\r\n _listScope: IListScope;\r\n}\r\n\r\n@NgComponent({\r\n token: Token.KbListItem,\r\n dependencies: [\r\n Token.$Timeout,\r\n ]\r\n})\r\nexport class KbListItem extends Directive {\r\n constructor($timeout: ng.ITimeoutService) {\r\n super();\r\n\r\n this.require = \"^kbList\";\r\n this.replace = true;\r\n this.template = Dirs.component(\"kb-list-item\");\r\n this.restrict = \"AE\";\r\n this.scope = {\r\n selectable: \"=?\",\r\n item: \"=?\",\r\n image: \"@\",\r\n icon: \"@\",\r\n onDelete: \"&\",\r\n onDoubleClick: \"&\",\r\n deletable: \"=?\",\r\n childTemplate: \"@\"\r\n };\r\n this.transclude = true;\r\n\r\n this.controller = [\r\n \"$scope\",\r\n \"$element\",\r\n \"$attrs\",\r\n \"$transclude\",\r\n \"$templateCache\",\r\n Token.$Compile.key,\r\n Token.$Http.key,\r\n function(\r\n $scope: IListItemScope,\r\n $element: ng.IAugmentedJQuery,\r\n $attrs: ng.IAttributes,\r\n $transclude: ng.ITranscludeFunction,\r\n $templateCache: ng.ITemplateCacheService,\r\n $compile: ng.ICompileService,\r\n $http: ng.IHttpService) {\r\n this.scope = $scope;\r\n\r\n let processTemplateElement = $template => {\r\n // compile the template\r\n let compiled = $compile($template, $transclude);\r\n // append it to the label\r\n $element.html(\"\").append($template);\r\n // now link it to the parent scope(we don't want this scope because it's an isolate scope)\r\n compiled($scope.$parent);\r\n };\r\n\r\n // if a child template was provided, then use that instead of the transclusion content\r\n let templateName = $scope.childTemplate;\r\n let $template = angular.element($templateCache.get(templateName));\r\n if (!$template.length) {\r\n $http.get(templateName).then(response => {\r\n $templateCache.put(templateName, response.data);\r\n $template = >angular.element(response.data);\r\n processTemplateElement($template);\r\n });\r\n } else {\r\n processTemplateElement($template);\r\n }\r\n }];\r\n \r\n this.compile = (element, atts: any) => {\r\n if (angular.isUndefined(atts.selectable)) {\r\n atts.selectable = \"true\";\r\n }\r\n if (angular.isUndefined(atts.deletable)) {\r\n atts.deletable = \"true\";\r\n }\r\n return this.link;\r\n };\r\n\r\n this.link = (scope: IListItemScope, element: ng.IAugmentedJQuery, atts, listController: IListController) => {\r\n // get parent scopes to use for selection and expansion\r\n let listScope = listController.scope;\r\n scope._listScope = listScope;\r\n // register the item with the parent kbList\r\n listController.registerListItem(scope);\r\n \r\n scope._itemClick = e => {\r\n // select the item if it's selectable\r\n if (listScope.selectable && scope.selectable) {\r\n // set the selected item on the tree so it can be bound to by controllers\r\n // if (listScope.multiple && e.)\r\n let mouseEvent = e as any;\r\n if (listScope.multiple) {\r\n if (mouseEvent.ctrlKey) {\r\n listScope.addToSelectedItems(scope.item);\r\n } else if (mouseEvent.shiftKey) {\r\n listScope.shiftToSelectedItems(scope.item);\r\n } else {\r\n listScope.setSelectedItems(scope.item);\r\n }\r\n } else {\r\n listScope.selectedItem = scope.item;\r\n }\r\n }\r\n };\r\n\r\n scope._itemDoubleClick = e => {\r\n scope.onDoubleClick();\r\n };\r\n };\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport * as angular from \"angular\";\r\nimport { IListItemScope } from \"@app/components/kb-list/kb-list-item.component\";\r\n\r\nexport interface IListScope extends ng.IScope {\r\n /**\r\n * If selection is multiple, then holds the selected items\r\n */\r\n selectedItems: any[];\r\n selectedItem: any;\r\n /**\r\n * 'cards' makes it wrap boxes (like the media list)\r\n */\r\n skin: string;\r\n /**\r\n * controls whether the items in the list can be selected. \r\n * If true, Each item can individually control whether they are selectable as well\r\n */\r\n selectable: boolean;\r\n /**\r\n * if multiple simultaneous selections can be made\r\n */\r\n multiple: boolean;\r\n isSelected: ($id: any) => boolean;\r\n addToSelectedItems: (item: any, doNotAutoRemove?: boolean) => void;\r\n setSelectedItems: (item: any) => void;\r\n shiftToSelectedItems: (item: any) => void;\r\n\r\n // internal scope properties\r\n _selectedListItems: IListItemScope[];\r\n _selectedListItem: IListItemScope;\r\n _listItems: IListItemScope[];\r\n}\r\n\r\nexport interface IListController {\r\n scope: IListScope;\r\n registerListItem: (item: IListItemScope) => void;\r\n}\r\n\r\n/**\r\n * kbList\r\n *\r\n * to use kbList, you nest kb-list-item directives inside of a kb-list directive:\r\n * \r\n * \r\n * \r\n *\r\n */\r\n\r\n@NgComponent({\r\n token: Token.KbList,\r\n dependencies: [\r\n ]\r\n})\r\nexport class KbList extends Directive {\r\n constructor() {\r\n\r\n super();\r\n\r\n this.replace = true;\r\n this.template = Dirs.component(\"kb-list\");\r\n this.restrict = \"AE\";\r\n this.scope = {\r\n selectedItem: \"=\",\r\n selectedItems: \"=?\",\r\n skin: \"@\",\r\n multiple: \"=?\",\r\n selectable: \"=?\"\r\n };\r\n this.transclude = true;\r\n\r\n // add scope defaults to the compile function\r\n this.compile = (element, atts: any) => {\r\n if (angular.isUndefined(atts.selectable)) {\r\n atts.selectable = \"true\";\r\n }\r\n };\r\n\r\n this.controller = [\r\n \"$scope\",\r\n \"$element\",\r\n \"$attrs\",\r\n \"$transclude\",\r\n function(\r\n $scope: IListScope,\r\n $element: ng.IAugmentedJQuery,\r\n $attrs: ng.IAttributes,\r\n $transclude: ng.ITranscludeFunction) {\r\n // set the scope of the tree on it's controller so children can access it\r\n this.scope = $scope;\r\n $scope._listItems = [];\r\n\r\n $scope.isSelected = $id => {\r\n if ($scope.multiple) {\r\n return ($scope._selectedListItems.some(li => li.$id == $id));\r\n }\r\n return ($scope._selectedListItem ? $scope._selectedListItem.$id == $id : false);\r\n };\r\n\r\n let lastSelectedItem = -1;\r\n\r\n $scope.addToSelectedItems = (item, doNotAutoRemove?: boolean) => {\r\n if (!doNotAutoRemove && $scope.selectedItems.indexOf(item) > -1) {\r\n $scope.selectedItems.remove(item);\r\n return;\r\n }\r\n $scope.selectedItems.push(item);\r\n lastSelectedItem = $scope._listItems.map(i => i.item).indexOf(item);\r\n };\r\n\r\n $scope.setSelectedItems = item => {\r\n $scope.selectedItems.clear();\r\n $scope.selectedItems.push(item);\r\n lastSelectedItem = $scope._listItems.map(i => i.item).indexOf(item);\r\n };\r\n\r\n $scope.shiftToSelectedItems = item => {\r\n if (lastSelectedItem < 0) {\r\n $scope.setSelectedItems(item);\r\n }\r\n let newIdx = $scope._listItems.map(i => i.item).indexOf(item);\r\n let i = (newIdx > lastSelectedItem ? lastSelectedItem + 1 : lastSelectedItem - 1);\r\n let check = () => {\r\n if (newIdx > lastSelectedItem) return i <= newIdx;\r\n return i >= newIdx;\r\n };\r\n let increment = () => {\r\n if (newIdx > lastSelectedItem) i++;\r\n else i--;\r\n };\r\n for (; check(); increment()) {\r\n $scope.addToSelectedItems($scope._listItems[i].item, true);\r\n }\r\n lastSelectedItem = newIdx;\r\n };\r\n\r\n // all child nodes register themselves with the tree to handle selection and accordion functionality\r\n this.registerListItem = (listItem: IListItemScope) => {\r\n $scope._listItems.push(listItem);\r\n listItem.$on(\"$destroy\", event => {\r\n $scope._listItems.remove(listItem);\r\n });\r\n };\r\n\r\n let selectFirstItem = () => {\r\n if ($scope._listItems.length) {\r\n if ($scope.multiple) {\r\n $scope._selectedListItems = [$scope._listItems.first()];\r\n $scope.selectedItems = [$scope._selectedListItems.first().item];\r\n } else {\r\n $scope._selectedListItem = $scope._listItems.first();\r\n $scope.selectedItem = $scope._selectedListItem.item;\r\n }\r\n }\r\n };\r\n\r\n let updateSelectedItem = () => {\r\n $scope._selectedListItems = [];\r\n $scope._selectedListItem = undefined;\r\n\r\n if ((!$scope.multiple && !$scope.selectedItem) ||\r\n ($scope.multiple && (!$scope.selectedItems ||\r\n !$scope.selectedItems.length))\r\n ) {\r\n selectFirstItem();\r\n } else {\r\n for (let listItem of $scope._listItems) {\r\n if (!$scope.multiple && $scope.selectedItem == listItem.item) {\r\n $scope._selectedListItem = listItem;\r\n } else if ($scope.multiple && $scope.selectedItems.indexOf(listItem.item) > -1) {\r\n $scope._selectedListItems.push(listItem);\r\n }\r\n }\r\n\r\n // if listitem is still undefined, the selected item is no longer in the list, so we reset it\r\n if ($scope.multiple && !$scope._selectedListItems.length) {\r\n $scope.selectedItems = [];\r\n } else if (!$scope.multiple && !$scope._selectedListItem) {\r\n $scope.selectedItem = undefined;\r\n }\r\n }\r\n };\r\n // if the consumer changes the selected item, we update the selected node\r\n if ($scope.multiple) {\r\n $scope.$watchCollection(\"selectedItems\", () => {\r\n updateSelectedItem();\r\n });\r\n } else {\r\n $scope.$watch(\"selectedItem\", () => {\r\n updateSelectedItem();\r\n });\r\n }\r\n // nodes might be added after the selectedItem is set by the consumer, so\r\n // we need to refind the selected node when the nodes collection changes\r\n $scope.$watchCollection(\"_listItems\", () => {\r\n // if (!$scope._selectedListItem) {\r\n updateSelectedItem();\r\n // }\r\n });\r\n }];\r\n }\r\n\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs, eBundle } from \"@app/helpers/dirs\";\r\n\r\nexport interface IMarkdownViewerScope extends ng.IScope {\r\n ngModel: string;\r\n _html: string;\r\n}\r\n/**\r\n * Given markdown text in the ngModel, will display the html\r\n */\r\n@NgComponent({\r\n token: Token.KbMarkdownViewer\r\n})\r\nexport class KbMarkdownViewer extends Directive {\r\n constructor() {\r\n super();\r\n this.scope = {\r\n ngModel: \"=\"\r\n };\r\n\r\n this.restrict = \"E\";\r\n this.template = Dirs.component(\"kb-markdown-viewer\", eBundle.app);\r\n this.replace = true;\r\n this.require = \"ngModel\";\r\n\r\n this.link = (scope: IMarkdownViewerScope, element: JQuery, atts, ngModel: ng.INgModelController) => {\r\n // override the onPrepareImage from the markdown library so that we can have our\r\n // custom image size add-on. \r\n // to control size of images, append =heightxwidth to the end of the url\r\n // some markdown implementations have a space before the equals sign, but\r\n // that doesn't seem to be possible here because markdownDeep won't recognize it\r\n // as an image at all\r\n MarkdownDeep.Markdown.prototype.OnPrepareImage = (tag: HTMLElement) => {\r\n let re = /=(\\w+)x(\\w+)$/;\r\n let src: string = tag.attributes[\"src\"];\r\n let parts = src.match(re);\r\n if (parts && parts[0]) {\r\n tag.attributes[\"src\"] = src.substr(0, src.length - parts[0].length);\r\n tag.attributes[\"width\"] = parts[1];\r\n tag.attributes[\"height\"] = parts[2];\r\n }\r\n };\r\n\r\n ngModel.$render = () => { // called when the binding has been changed by the consumer\r\n // Create an instance of Markdown\r\n let md = new MarkdownDeep.Markdown();\r\n md.NewWindowForExternalLinks = true;\r\n let v = ngModel.$viewValue;\r\n scope._html = v? md.Transform(v): null;\r\n };\r\n\r\n };\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\n@NgComponent({\r\n token: Token.KbMax,\r\n dependencies: [\r\n ]\r\n})\r\nexport class KbMax extends Directive {\r\n constructor() {\r\n super();\r\n this.restrict = \"A\";\r\n this.require = \"ngModel\";\r\n \r\n this.link = (scope, elem, attr, ctrl) => {\r\n let maxValidator = value => {\r\n let max = scope.$eval(attr.ngMax) || Infinity;\r\n if (ctrl.$viewValue && ctrl.$viewValue > max) {\r\n $(elem).val(max);\r\n return max;\r\n }\r\n return value;\r\n };\r\n\r\n ctrl.$parsers.push(maxValidator);\r\n ctrl.$formatters.push(maxValidator);\r\n };\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { IRootScope } from \"@models\";\r\nimport { DialogService } from \"@app/services/dialog.service\";\r\n\r\n@NgComponent({\r\n token: Token.KbMediaList,\r\n dependencies: [\r\n Token.$RootScope,\r\n Token.DialogService,\r\n ]\r\n})\r\nexport class KbMediaList extends Directive {\r\n constructor(\r\n private $rootScope: IRootScope,\r\n private dialogService: DialogService\r\n ) {\r\n super();\r\n\r\n this.replace = true;\r\n // this.require = 'ngModel';\r\n this.template = Dirs.component(\"kb-media-list\");\r\n this.restrict = \"E\";\r\n this.scope = {\r\n ngModel: \"=\",\r\n addItem: \"&\",\r\n imagePath: \"@\"\r\n };\r\n\r\n this.link = (scope: any, element, atts: any) => {\r\n scope.isEnabled = () => {\r\n return !($(element).hasClass(\"disabled\") || $(element).attr(\"disabled\"));\r\n };\r\n\r\n scope.options = {\r\n start(e, ui) {\r\n $(e.target).data(\"ui-sortable\").floating = true;\r\n },\r\n tolerance: \"pointer\"\r\n } as JQueryUI.SortableOptions;\r\n\r\n // element.sortable({\r\n // items: \"li:not(#btn-add-image)\",\r\n // tolerance: \"pointer\"\r\n // });\r\n\r\n scope.deleteItem = (index: number) => {\r\n scope.ngModel.splice(index, 1);\r\n };\r\n };\r\n }\r\n\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { IFileIdFilter } from \"@app/filters/file-id.filter\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { DialogService } from \"@app/services/dialog.service\";\r\nimport { DrawerService } from \"@app/services/drawer.service\";\r\nimport { KbService } from \"@app/services/kb.service\";\r\nimport { UploadService } from \"@app/services/upload.service\";\r\nimport { DialogButton, eAlertType, IDialog, IMediaObject, InputDialogButton, IRootScope } from \"@models\";\r\nimport { icons } from \"@tools\";\r\nimport * as angular from \"angular\";\r\n\r\nexport interface IMediaManagerScope extends ng.IScope {\r\n isDialog: boolean;\r\n apiPath: string;\r\n rootDir: string;\r\n startPath: string;\r\n\r\n isReadOnly: boolean;\r\n\r\n addFolder: () => void;\r\n fileDoubleClicked: (file: IMediaObject) => void;\r\n open: (args: any) => void;\r\n upload: () => void;\r\n deleteItems: () => void;\r\n rename: () => void;\r\n refresh: () => void;\r\n files: IMediaObject[];\r\n // uploadOptions: kendo.ui.UploadOptions;\r\n // listSource: kendo.data.DataSource;\r\n crumbs: ICrumb[];\r\n crumbClick: (crumb: ICrumb) => void;\r\n selectedFiles: IMediaObject[];\r\n selectedFile: IMediaObject;\r\n multiple: boolean;\r\n\r\n uploadingFiles: any[];\r\n uploading: boolean;\r\n addBlank: (ext: string) => void;\r\n\r\n tracker: ng.IPromiseTracker; // tracker is passed in from the outside. It should be used when making http calls\r\n}\r\n\r\nexport interface ICrumb {\r\n url: string;\r\n name: string;\r\n icon: string;\r\n}\r\n \r\n@NgComponent({\r\n token: Token.KbMediaManager,\r\n dependencies: [\r\n Token.$Window,\r\n Token.$Http,\r\n Token.KbService,\r\n Token.DialogService,\r\n Token.$RootScope,\r\n Token.DrawerService,\r\n Token.UploadService,\r\n Token.$Q,\r\n Token.$Filter,\r\n Token.$Timeout,\r\n ]\r\n})\r\nexport class KbMediaManager extends Directive {\r\n\r\n constructor(\r\n private $window: ng.IWindowService,\r\n private $http: ng.IHttpService,\r\n private kbService: KbService,\r\n private dialogService: DialogService,\r\n private $rootScope: IRootScope,\r\n private drawerService: DrawerService,\r\n private uploadService: UploadService,\r\n private $q: ng.IQService,\r\n private $filter: ng.IFilterService,\r\n private $timeout: ng.ITimeoutService) {\r\n\r\n super();\r\n\r\n this.restrict = \"E\";\r\n this.template = Dirs.component(\"kb-media-manager\");\r\n this.scope = {\r\n dialog: \"@\",\r\n multiple: \"=?\",\r\n selectedFile: \"=?\",\r\n selectedFiles: \"=?\",\r\n filter: \"@\",\r\n apiPath: \"@\",\r\n rootDir: \"@\",\r\n startPath: \"@\",\r\n open: \"&\",\r\n tracker: \"=?\"\r\n };\r\n this.replace = true;\r\n \r\n this.link = (scope: IMediaManagerScope, element, atts: any) => {\r\n\r\n this.atts = atts;\r\n this.mscope = scope;\r\n if (!this.mscope.apiPath) this.mscope.apiPath = \"api/media\";\r\n if (!this.mscope.rootDir) this.mscope.rootDir = \"media\";\r\n\r\n if (typeof atts.multiple == \"undefined\") {\r\n scope.multiple = true;\r\n }\r\n \r\n scope.isDialog = (atts.dialog == \"true\");\r\n\r\n scope.isReadOnly = !this.$rootScope.user.canModifyMedia || this.$rootScope.environment != \"dev\";\r\n \r\n scope.deleteItems = () => {\r\n this.deleteSelectedListItems();\r\n };\r\n\r\n scope.refresh = () => {\r\n this.refreshList();\r\n };\r\n\r\n scope.rename = () => {\r\n this.rename();\r\n };\r\n\r\n scope.addFolder = () => {\r\n this.addFolder();\r\n };\r\n\r\n scope.fileDoubleClicked = (file: IMediaObject) => {\r\n // if this is a folder, then navigate to the folder. If a file, then call the handler of the consumer\r\n if (!file.isFile) {\r\n this.navigate(file.relativePath);\r\n } else {\r\n if (scope.open) {\r\n scope.open({ file }); // call the handler of the consumer\r\n }\r\n }\r\n };\r\n\r\n scope.upload = (accept?: string) => {\r\n this.uploadService.promptUserToChooseFiles().then(files => {\r\n this.onUpload({\r\n files\r\n });\r\n // setTimeout(() =>\r\n // {\r\n let promises = [];\r\n files.forEach(file => {\r\n let p = this.uploadService.uploadFileToMedia(file, this.currentDir, this.mscope.apiPath);\r\n promises.push(p.then(() => {\r\n this.uploadProgress({\r\n files: [file],\r\n percentComplete: 100\r\n });\r\n }, () => {\r\n this.uploadError({\r\n files: [file]\r\n });\r\n }, (e: ProgressEvent) => {\r\n this.uploadProgress({\r\n files: [file],\r\n percentComplete: ((e.loaded / e.total) * 100)\r\n });\r\n }));\r\n });\r\n this.$q.all(promises).finally(() => this.uploadComplete());\r\n // }, 500);\r\n });\r\n };\r\n \r\n scope.crumbClick = crumb => {\r\n this.navigate(crumb.url);\r\n };\r\n\r\n scope.addBlank = ext => {\r\n this.dialogService.input({\r\n msg: \"Select a name for the new file\",\r\n inputType: \"text\",\r\n value: \"New File\",\r\n buttons: [\r\n new InputDialogButton(loc.ok, icons.success, args => {\r\n if (args.value) {\r\n $http.post(\"/api/templates/blank\", {\r\n relativePath: this.currentDir + args.value + \".\" + ext\r\n }, { tracker: scope.tracker }).then(response => {\r\n this.refreshList();\r\n });\r\n }\r\n }),\r\n new InputDialogButton(loc.cancel, icons.cancel, args => {\r\n\r\n })\r\n ]\r\n });\r\n };\r\n\r\n scope.files = [];\r\n\r\n if (!scope.isDialog) {\r\n if ($rootScope.user.canModifyMedia && this.$rootScope.environment == \"dev\") {\r\n let drAddFolder = drawerService.addDrawer(icons.addFolder, loc.addfolder, scope.addFolder);\r\n }\r\n \r\n let drOpen = drawerService.addDrawer(\r\n icons.open, loc.open, () => scope.fileDoubleClicked(this.selectedItem()));\r\n\r\n if ($rootScope.user.canModifyMedia && this.$rootScope.environment == \"dev\") {\r\n let drUpload = drawerService.addDrawer(icons.upload, loc.upload, scope.upload);\r\n\r\n let drDelete = drawerService.addDrawer(icons.deleter, loc.deleter, scope.deleteItems);\r\n let drRename = drawerService.addDrawer(icons.rename, loc.rename, scope.rename);\r\n }\r\n let drRefresh = drawerService.addDrawer(icons.refresh, loc.refresh, scope.refresh);\r\n }\r\n\r\n // setup root crumb\r\n let startDir = scope.startPath ? this.getDirectory(scope.startPath) : \"\";\r\n this.navigate(startDir);\r\n \r\n };\r\n }\r\n\r\n private currentDir: string;\r\n private mscope: IMediaManagerScope;\r\n private uploadDialog: IDialog;\r\n private atts;\r\n \r\n private getChildren = (dir: string) => {\r\n let params = $.param($.extend({dir}, { filter: this.atts.filter }));\r\n let url = this.mscope.apiPath + \"/children?\" + params;\r\n this.$http.get(url, { tracker: this.mscope.tracker }).then(r => {\r\n this.mscope.files = r.data;\r\n this.$timeout(() => {\r\n if (this.mscope.startPath) {\r\n let startFile = this.mscope.files.find(f => f.relativePath == this.mscope.startPath);\r\n if (startFile) this.mscope.selectedFile = startFile;\r\n this.mscope.startPath = null;\r\n }\r\n }, 0);\r\n });\r\n }\r\n\r\n private getDirectory = (path: string) => {\r\n let index = path.indexOf(\"/\");\r\n if (index > -1) {\r\n return path.substr(0, index);\r\n }\r\n return \"\";\r\n }\r\n \r\n private navigate(dir: string) {\r\n this.currentDir = dir;\r\n this.refreshCrumbs(dir );\r\n this.getChildren(dir);\r\n // this.mscope.listSource.read({ id: dir }); \r\n }\r\n\r\n private refreshCrumbs(dir: string) {\r\n this.mscope.crumbs = [];\r\n\r\n this.mscope.crumbs.push({ url: \"\", name: this.mscope.rootDir, icon: icons.image } as ICrumb);\r\n\r\n let segments: string[] = dir.split(\"/\");\r\n\r\n for (let index = 0; index < segments.length; index++) {\r\n let segment = segments[index];\r\n if (segment) {\r\n // calculate the absolute url of the segment\r\n let url: string = \"\";\r\n for (let i = 0; i <= index; i++) {\r\n url += segments[i] + \"/\";\r\n }\r\n this.mscope.crumbs.push({ url, name: segment, icon: icons.crumb } as ICrumb);\r\n }\r\n }\r\n }\r\n\r\n private deleteSelectedListItems() {\r\n this.dialogService.dialog({\r\n content: loc.msg_deletemedia,\r\n buttons: [\r\n new DialogButton(loc.ok, icons.success, () => {\r\n let ids: string[] = new Array();\r\n let selected = this.getListViewSelectedItems();\r\n\r\n selected.forEach(mobject => {\r\n this.$http.delete(this.mscope.apiPath,\r\n {\r\n params: {\r\n relativePath: mobject.relativePath\r\n },\r\n headers:\r\n {\r\n \"Content-Type\": \"application/json\"\r\n }\r\n });\r\n });\r\n \r\n // delete the stuff directly in the source so the user doesn't have to wait\r\n $.each(selected, (index: number, mobject: IMediaObject) => {\r\n // now remove the item from the listview\r\n this.mscope.files.remove(mobject);\r\n // (this.mscope.listSource).remove(mobject);\r\n });\r\n }),\r\n new DialogButton(loc.cancel, icons.cancel, args => {\r\n })\r\n ]\r\n \r\n });\r\n }\r\n \r\n private rename() {\r\n let selectedItems = this.getListViewSelectedItems();\r\n if (selectedItems && selectedItems.length > 0) {\r\n let item = selectedItems[0];\r\n let msg = item.isFile ? loc.msg_renamefile : loc.msg_renamefolder;\r\n\r\n this.dialogService.input({\r\n msg,\r\n value: item.name,\r\n buttons: [\r\n new InputDialogButton(loc.ok, icons.success, args => {\r\n this.$http.post(this.mscope.apiPath + \"/rename\", {\r\n relativePath: item.relativePath, newName: args.value\r\n }, { tracker: this.mscope.tracker })\r\n .then(() => {\r\n this.refreshList();\r\n }, (e) => {\r\n this.dialogService.alert({\r\n msg: \"Rename failed. Please ensure your filename does not contains slashes.\",\r\n type: eAlertType.error\r\n });\r\n });\r\n }),\r\n new InputDialogButton(loc.cancel, icons.cancel, args => {\r\n })\r\n\r\n ]\r\n\r\n });\r\n }\r\n }\r\n \r\n private addFolder() {\r\n this.dialogService.input({\r\n msg: loc.msg_renamefolder,\r\n value: loc.newfolder,\r\n buttons: [\r\n new InputDialogButton(loc.ok, icons.success, args => {\r\n this.$http.post(this.mscope.apiPath + \"/addfolder\", {\r\n dir: this.currentDir, folderName: args.value\r\n }, { tracker: this.mscope.tracker })\r\n .then(() => {\r\n this.refreshList();\r\n });\r\n }),\r\n new InputDialogButton(loc.cancel, icons.cancel, args => {\r\n })\r\n\r\n ]\r\n\r\n });\r\n }\r\n\r\n private getListViewDataItem($domItem: JQuery): IMediaObject {\r\n let index: number = $domItem.index();\r\n return null;\r\n // return this.mscope.listSource.view()[index];\r\n }\r\n\r\n private getListViewSelectedItems(): IMediaObject[] {\r\n if (this.mscope.multiple) {\r\n return this.mscope.selectedFiles;\r\n }\r\n return [this.mscope.selectedFile];\r\n }\r\n\r\n public selectedItem(): IMediaObject {\r\n let selected = this.getListViewSelectedItems();\r\n if (selected) {\r\n return selected[0];\r\n }\r\n return null;\r\n }\r\n\r\n private refreshList() {\r\n this.getChildren(this.currentDir);\r\n }\r\n\r\n private onUpload(e) {\r\n if (!this.mscope.uploadingFiles) this.mscope.uploadingFiles = [];\r\n\r\n angular.forEach(e.files, (item, index) => {\r\n item.percentComplete = 0;\r\n this.mscope.uploadingFiles.push(item);\r\n });\r\n\r\n if (!this.mscope.uploading) {\r\n \r\n this.uploadDialog = this.dialogService.dialog({\r\n template: Dirs.view(\"dialog-upload-files\"),\r\n scope: this.mscope.$new(),\r\n buttons: [\r\n new InputDialogButton(loc.ok, icons.success, args => {\r\n this.mscope.uploadingFiles = null;\r\n this.refreshList();\r\n }, false) // hide the ok button by passing in visible = false\r\n ]\r\n });\r\n \r\n }\r\n\r\n this.mscope.uploading = true;\r\n }\r\n\r\n private uploadProgress(e) {\r\n $.each(e.files, (index, file) => {\r\n let $li = $(\"#uploading-list #\" + ((this.$filter as any)(\"fileId\") as IFileIdFilter)(file.name));\r\n file.percentComplete = e.percentComplete;\r\n });\r\n }\r\n\r\n private uploadError(e) {\r\n $.each(e.files, (index, file: File) => {\r\n let $li = $(\"#uploading-list #\" + ((this.$filter as any)(\"fileId\") as IFileIdFilter)(file.name));\r\n $li.prepend('
' + icons.error + \"
\");\r\n });\r\n }\r\n\r\n private uploadComplete(e?) {\r\n this.mscope.uploading = false;\r\n // show the buttons in the dialog now\\\r\n this.uploadDialog.buttons[0].visible = true;\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { DialogService } from \"@app/services/dialog.service\";\r\nimport { KbService } from \"@app/services/kb.service\";\r\nimport { IRootScope, MediaDialogButton } from \"@models\";\r\nimport { icons } from \"@tools\";\r\n\r\nexport interface IMediaSelectScope extends ng.IScope {\r\n ngModel: string;\r\n\r\n isEnabled: () => boolean;\r\n clear: () => void;\r\n click: () => void;\r\n}\r\n\r\n@NgComponent({\r\n token: Token.KbMediaSelect,\r\n dependencies: [\r\n Token.KbService,\r\n Token.$RootScope,\r\n Token.DialogService,\r\n ]\r\n})\r\nexport class KbMediaSelect extends Directive {\r\n constructor(\r\n kbService: KbService,\r\n $rootScope: IRootScope,\r\n dialogService: DialogService\r\n ) {\r\n super();\r\n this.replace = true;\r\n this.restrict = \"E\";\r\n this.scope = {\r\n ngModel: \"=\"\r\n };\r\n this.template = Dirs.component(\"kb-media-select\");\r\n\r\n this.link = (scope: IMediaSelectScope, element, atts, ngModelController: ng.INgModelController) => {\r\n scope.isEnabled = () => {\r\n return !($(element).hasClass(\"disabled\") || $(element).attr(\"disabled\"));\r\n };\r\n\r\n scope.clear = () => {\r\n scope.ngModel = null;\r\n };\r\n\r\n scope.click = () => {\r\n if (scope.isEnabled()) {\r\n dialogService.mediaSelect({\r\n startPath: scope.ngModel,\r\n buttons: [\r\n new MediaDialogButton(loc.ok, icons.success, args => {\r\n scope.ngModel = args.selectedItem ? args.selectedItem.relativePath : null;\r\n }),\r\n new MediaDialogButton(loc.cancel, icons.cancel, args => {\r\n\r\n })\r\n ]\r\n });\r\n }\r\n };\r\n };\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { IMediaFilter } from \"@app/filters/media.filter\";\r\nimport { IThumbFilter } from \"@app/filters/thumb.filter\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { KbService } from \"@app/services/kb.service\";\r\nimport { StorageService } from \"@app/services/storage.service\";\r\nimport { IRootScope } from \"@models\";\r\nimport { extensions, Utils } from \"@tools\";\r\n\r\nexport interface IMediaViewerScope extends ng.IScope {\r\n /**\r\n * The path to the file\r\n */\r\n path: string;\r\n /**\r\n * Whether to show the media as a thumbnail or not\r\n */\r\n thumb: boolean; //\r\n /**\r\n * Whether to show the controls in the video player\r\n */\r\n controls: boolean;\r\n cachebuster: boolean;\r\n}\r\n \r\n@NgComponent({\r\n token: Token.KbMediaViewer,\r\n dependencies: [\r\n Token.$Filter,\r\n Token.KbService,\r\n Token.$Sce,\r\n Token.$RootScope,\r\n Token.StorageService\r\n ]\r\n})\r\nexport class KbMediaViewer extends Directive {\r\n constructor(\r\n $filter: ng.IFilterService,\r\n kbService: KbService,\r\n $sce: ng.ISCEService,\r\n $rootScope: IRootScope,\r\n storageService: StorageService\r\n ) {\r\n super();\r\n\r\n this.replace = true;\r\n this.restrict = \"EA\";\r\n this.template = Dirs.component(\"kb-media-viewer\");\r\n this.scope = {\r\n path: \"=\",\r\n thumb: \"@\",\r\n cachebuster: \"=?\"\r\n };\r\n\r\n this.link = (scope: any, element, atts: any) => {\r\n \r\n //// for some reason the classes aren't getting merged\r\n //// but it is shown correctly in atts. Here's a workaround\r\n // element.removeClass();\r\n // element.addClass(atts.class);\r\n scope.fallback = storageService.getFallbackImage();\r\n\r\n scope.$watch(\"path\", newValue => {\r\n scope.ext = kbService.getExtension(scope.path);\r\n if (scope.ext == \"ogv\") scope.ext = \"ogg\";\r\n\r\n if (extensions.image.indexOf(scope.ext) != -1) {\r\n scope.type = \"image\";\r\n if (scope.thumb) {\r\n scope.fullPath = (($filter as any)(\"thumb\") as IThumbFilter)(scope.path);\r\n } else {\r\n scope.fullPath = (($filter as any)(\"media\") as IMediaFilter)(scope.path);\r\n }\r\n } else if (extensions.video.indexOf(scope.ext) != -1) {\r\n scope.type = \"video\";\r\n scope.fullPath = (($filter as any)(\"media\") as IMediaFilter)(scope.path);\r\n }\r\n\r\n if (Utils.isAbsoluteUrl(scope.path)) {\r\n scope.fullPath = scope.path;\r\n }\r\n if (scope.cachebuster) {\r\n scope.fullPath = scope.fullPath + \"?v=\" + $rootScope.cacheBuster;\r\n }\r\n scope.fullPath = $sce.trustAsResourceUrl(scope.fullPath);\r\n });\r\n };\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { KbService } from \"@app/services/kb.service\";\r\nimport { IRootScope } from \"@models\";\r\nimport { StateService } from \"@uirouter/angularjs\";\r\n\r\nexport interface IMenuItemScope extends ng.IScope {\r\n icon: string;\r\n label: string;\r\n}\r\n\r\n@NgComponent({\r\n token: Token.KbMenuItem,\r\n dependencies: [\r\n Token.KbService,\r\n Token.$State,\r\n Token.$RootScope,\r\n ]\r\n})\r\nexport class KbMenuItem extends Directive {\r\n constructor(\r\n private kbService: KbService,\r\n $state: StateService,\r\n $rootScope: IRootScope\r\n ) {\r\n super();\r\n\r\n this.restrict = \"E\";\r\n this.template = Dirs.component(\"kb-menu-item\");\r\n this.scope = {\r\n icon: \"@\",\r\n label: \"@\",\r\n params: \"=?\"\r\n };\r\n this.replace = true;\r\n this.transclude = true;\r\n\r\n this.link = (scope: IMenuItemScope, element, atts) => {\r\n // remove the submenu element if there are no sub menu items\r\n let $subMenu = element.find(\".kb-menu__sub\");\r\n if (!$subMenu.html().length) {\r\n $subMenu.remove();\r\n }\r\n\r\n element.click(() => {\r\n let isExpanded = $(element).hasClass(\"is-expanded\");\r\n $(element).children(\".kb-menu__item\").removeClass(\"is-expanded\");\r\n\r\n if (!isExpanded) {\r\n $(element).addClass(\"is-expanded\");\r\n let collapse = () => {\r\n $(element).removeClass(\"is-expanded\");\r\n $(\"html\").unbind(\"click\", collapse);\r\n };\r\n setTimeout(() => { $(\"html\").bind(\"click\", collapse); }, 1);\r\n }\r\n });\r\n\r\n scope.$on(\"$destroy\", () => {\r\n element.off();\r\n });\r\n };\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { StateService } from \"@uirouter/angularjs\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { KbService } from \"@app/services/kb.service\";\r\nimport { IRootScope } from \"@models\";\r\n\r\n@NgComponent({\r\n token: Token.KbMenu,\r\n dependencies: [\r\n Token.KbService,\r\n Token.$RootScope,\r\n Token.$State,\r\n ]\r\n})\r\nexport class KbMenu extends Directive {\r\n constructor(\r\n private kbService: KbService,\r\n $rootScope: IRootScope,\r\n $state: StateService\r\n ) {\r\n super();\r\n\r\n this.restrict = \"E\";\r\n this.template = Dirs.component(\"kb-menu\");\r\n this.scope = true;\r\n this.replace = true;\r\n this.transclude = true;\r\n\r\n this.link = (scope, element, atts) => {\r\n\r\n };\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\n@NgComponent({\r\n token: Token.KbMin,\r\n dependencies: [\r\n ]\r\n})\r\nexport class KbMin extends Directive {\r\n constructor() {\r\n super();\r\n this.restrict = \"A\";\r\n this.require = \"ngModel\";\r\n \r\n this.link = (scope, elem, attr, ctrl) => {\r\n let minValidator = value => {\r\n let min = scope.$eval(attr.ngMin) || 0;\r\n if (ctrl.$viewValue && ctrl.$viewValue < min) {\r\n $(elem).val(min);\r\n return min;\r\n }\r\n return value;\r\n };\r\n\r\n ctrl.$parsers.push(minValidator);\r\n ctrl.$formatters.push(minValidator);\r\n };\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { KbService } from \"@app/services/kb.service\";\r\n\r\ninterface IMoneyScope extends ng.IScope {\r\n currency: string;\r\n}\r\n\r\n@NgComponent({\r\n token: Token.KbMoney,\r\n dependencies: [\r\n Token.KbService,\r\n Token.$RootScope\r\n ]\r\n})\r\nexport class KbMoney extends Directive {\r\n constructor(\r\n private kbService: KbService,\r\n private $rootScope\r\n ) {\r\n super();\r\n this.template = '';\r\n\r\n this.restrict = \"E\";\r\n this.scope = {\r\n label: \"@\",\r\n ngModel: \"=\",\r\n currency: \"@\"\r\n };\r\n this.require = \"?ngModel\";\r\n this.replace = true;\r\n this.transclude = true;\r\n\r\n this.link = (\r\n scope: IMoneyScope,\r\n element: ng.IAugmentedJQuery,\r\n atts: ng.IAttributes,\r\n ngModel: ng.INgModelController\r\n ) => {\r\n\r\n let update = v => {\r\n return v ?\r\n kbService.fxConvert(\r\n parseFloat(v),\r\n this.$rootScope.companySettings.currency.toUpperCase(), scope.currency)\r\n : 0;\r\n };\r\n\r\n scope.$watch(\"currency\", () => {\r\n ngModel.$modelValue = (update(ngModel.$viewValue));\r\n });\r\n\r\n ngModel.$formatters.push(v => v ? kbService.fxConvert(parseFloat(v), scope.currency) : 0);\r\n ngModel.$parsers.push(update);\r\n };\r\n }\r\n}\r\n","import { IInputScope, KbInput } from \"@app/components/kb-input/kb-input.component\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { keyboard, Utils } from \"@tools\";\r\nimport * as angular from \"angular\";\r\n\r\ninterface IMultiAutoCompleteScope extends IInputScope {\r\n // external members\r\n source: any;\r\n ngModel: any[];\r\n /**\r\n * should it restrict ngModel values to ones selected in the dropdown\r\n */\r\n editable: boolean;\r\n /**\r\n * used to figure out which property from the source items should be compared to what the user is typing in\r\n */\r\n valueField: string;\r\n /**\r\n * ask the consumer to build the item given the user input. (value: string) => ng.IPromise\r\n */\r\n buildItem: any;\r\n ngDisabled: boolean;\r\n \r\n // internal directive members\r\n _matches: any[];\r\n _userInput: string;\r\n _dropdownOpen: boolean;\r\n _selectMatch: (item: any) => void;\r\n _isActive: (index: number) => boolean;\r\n _selectActive: (index: number) => void;\r\n _delete: (item: any) => void;\r\n _click: () => void;\r\n _activeIndex: number;\r\n _loading: boolean;\r\n _isEnabled: () => boolean;\r\n _highlightedItems: any;\r\n _itemMousedown: (e: ng.IAngularEvent, item: any) => void;\r\n}\r\n\r\n@NgComponent({\r\n token: Token.KbMultiAutoComplete,\r\n dependencies: [\r\n Token.$Q,\r\n Token.$Timeout\r\n ]\r\n})\r\nexport class KbMultiAutoComplete extends KbInput {\r\n constructor(\r\n $q: ng.IQService,\r\n $timeout: ng.ITimeoutService\r\n ) {\r\n super($timeout);\r\n\r\n this.restrict = \"EA\";\r\n this.template = Dirs.component(\"kb-multi-auto-complete\");\r\n this.scope = Utils.extend(this.scope, {\r\n source: \"&\",\r\n buildItem: \"&\",\r\n editable: \"@\", // should it restrict ngModel values to ones selected in the dropdown\r\n valueField: \"@\"\r\n });\r\n this.replace = true;\r\n this.transclude = {\r\n header: \"?kbMultiAutoCompleteHeader\",\r\n dropdown: \"?kbMultiAutoCompleteDropdown\"\r\n };\r\n\r\n this.link = (scope: IMultiAutoCompleteScope, element: JQuery, atts: any, controllers: any[]) => {\r\n this.kbInputLinkFn(scope, element, atts, controllers);\r\n let ngModelCtrl = controllers[0] as ng.INgModelController;\r\n if (!atts.ngModel) throw new Error(\"ngModel is required for kbAutoSelect\");\r\n if (!angular.isFunction(scope.source)) {\r\n throw new Error(\"source for kbMultiAutoComplete must be a function that accepts the current query\");\r\n }\r\n if (scope.buildItem && !angular.isFunction(scope.buildItem)) {\r\n throw new Error(\"buildItem for kbMultiAutoComplete must be a function that accepts the current query\");\r\n }\r\n scope._userInput = null;\r\n scope._matches = [];\r\n scope._dropdownOpen = false;\r\n scope._loading = false;\r\n scope._highlightedItems = {};\r\n let editable = scope.$parent.$eval(atts.editable) == true;\r\n let $input = element.find(\"input\");\r\n\r\n scope._isEnabled = () => {\r\n return !scope.ngDisabled;\r\n };\r\n\r\n let isFocused = () => {\r\n return element.hasClass(\"focus\");\r\n };\r\n\r\n let getMatches = () => {\r\n let lastUserInput = scope._userInput;\r\n scope._loading = true;\r\n let promise = $q.when(scope.source({ query: scope._userInput }));\r\n promise.then(data => {\r\n // it might happen that several async queries were in progress if a user were typing fast\r\n // but we are interested only in responses that correspond to the current view value\r\n if (lastUserInput === scope._userInput) {\r\n scope._matches.clear();\r\n scope._matches.pushArray(data);\r\n scope._activeIndex = -1;\r\n scope._dropdownOpen = scope._matches.length > 0;\r\n scope._loading = false;\r\n }\r\n });\r\n };\r\n\r\n scope.$watch(\"_userInput\", (newUserInput: string) => {\r\n if (!newUserInput) {\r\n scope._matches.clear();\r\n scope._dropdownOpen = false;\r\n $input.attr(\"size\", 0);\r\n } else {\r\n $input.attr(\"size\", newUserInput.length);\r\n getMatches();\r\n }\r\n });\r\n\r\n let getValue = (item: any) => {\r\n if (item == null) return null;\r\n if (scope.valueField) return item[scope.valueField];\r\n return item;\r\n };\r\n\r\n let buildItem = (value: any) => {\r\n let item = null;\r\n if (value) {\r\n if (scope.valueField) {\r\n item = {};\r\n item[scope.valueField] = value;\r\n } else {\r\n item = value;\r\n }\r\n // we will add the item right away but come back to it with any modifications from the consumer\r\n $q.when(scope.buildItem({ value })).then(builtItem => {\r\n $.extend(item, builtItem);\r\n });\r\n }\r\n return item;\r\n };\r\n\r\n scope._selectMatch = item => {\r\n if (scope._isEnabled() && item) {\r\n let existingItem = scope.ngModel.find(i => getValue(i) == getValue(item));\r\n if (!existingItem) {\r\n // if (typeof item != \"string\") scope.ngModel.push(item);\r\n // else if (atts[\"valueField\"]) scope.ngModel.push({name: item});\r\n // else scope.ngModel.push(item);\r\n scope.ngModel.push(item);\r\n } else {\r\n scope._highlightedItems[(existingItem.name ? existingItem.name : existingItem)] = true;\r\n setTimeout(() => {\r\n scope.$apply((scope: IMultiAutoCompleteScope) => {\r\n scope._highlightedItems[(existingItem.name ? existingItem.name : existingItem)] = false;\r\n });\r\n }, 500);\r\n }\r\n scope._userInput = \"\";\r\n }\r\n };\r\n\r\n scope._itemMousedown = (e: ng.IAngularEvent, item) => {\r\n e.preventDefault(); // so we don't lose focus and trigger the blur event\r\n scope._selectMatch(item);\r\n };\r\n\r\n scope._delete = item => {\r\n if (scope._isEnabled()) {\r\n scope.ngModel.remove(item);\r\n }\r\n };\r\n\r\n scope._click = () => {\r\n if (scope._isEnabled()) {\r\n $input.focus();\r\n }\r\n };\r\n\r\n scope._isActive = index => {\r\n return scope._activeIndex == index;\r\n };\r\n\r\n scope._selectActive = index => {\r\n scope._activeIndex = index;\r\n };\r\n\r\n let onDocumentClicked = (e: Event) => {\r\n if (editable) {\r\n scope.$apply(() => {\r\n scope._selectMatch(buildItem(scope._userInput));\r\n });\r\n }\r\n };\r\n\r\n $input[0].addEventListener(\"focus\", () => {\r\n element.addClass(\"focus\");\r\n });\r\n $input[0].addEventListener(\"blur\", () => {\r\n if (editable) {\r\n scope.$apply(() => {\r\n scope._selectMatch(buildItem(scope._userInput));\r\n });\r\n }\r\n element.removeClass(\"focus\");\r\n });\r\n\r\n // bind keyboard events: \r\n // backspace(8) \r\n // arrows up(38) /\r\n // down(40),\r\n // enter(13) and\r\n // tab(9),\r\n // esc(27),\r\n // space(32)\r\n // comma(188)\r\n $input.on(\"keydown\", (e: JQueryEventObject) => {\r\n if (e.which == keyboard.backspace) {\r\n if (!scope._userInput && scope.ngModel.length > 0) {\r\n scope.$apply(() => {\r\n scope.ngModel.pop();\r\n });\r\n }\r\n }\r\n\r\n if (e.which == keyboard.up) {\r\n e.preventDefault();\r\n scope.$apply(() => {\r\n if (scope._dropdownOpen) {\r\n scope._activeIndex -= 1;\r\n if (scope._activeIndex < 0) {\r\n scope._dropdownOpen = false;\r\n }\r\n }\r\n });\r\n }\r\n if (e.which == keyboard.down) {\r\n e.preventDefault();\r\n if (scope._activeIndex < scope._matches.length - 1) {\r\n scope.$apply(() => {\r\n scope._activeIndex += 1;\r\n scope._dropdownOpen = true;\r\n });\r\n }\r\n }\r\n if (e.which == keyboard.enter) {\r\n scope.$apply(() => {\r\n e.preventDefault();\r\n if (scope._dropdownOpen) {\r\n if (scope._matches.length > 0) {\r\n scope._selectMatch(scope._matches[(scope._activeIndex > 0 ? scope._activeIndex : 0)]);\r\n }\r\n } else if (editable) {\r\n scope._selectMatch(buildItem(scope._userInput));\r\n } else {\r\n scope._dropdownOpen = true;\r\n }\r\n });\r\n }\r\n if (e.which == keyboard.tab) {\r\n if (scope._dropdownOpen) {\r\n if (scope._matches) {\r\n scope.$apply(() => {\r\n scope._selectMatch(scope._matches[(scope._activeIndex > 0 ? scope._activeIndex : 0)]);\r\n });\r\n }\r\n e.stopPropagation();\r\n }\r\n }\r\n if (e.which == keyboard.escape) {\r\n e.preventDefault();\r\n scope.$apply(() => {\r\n scope._dropdownOpen = false;\r\n e.stopPropagation();\r\n });\r\n }\r\n if ((e.which == keyboard.comma) && editable) {\r\n e.preventDefault();\r\n scope.$apply(() => {\r\n scope._selectMatch(buildItem(scope._userInput));\r\n });\r\n }\r\n });\r\n\r\n scope.$on(\"$destroy\", () => {\r\n element.off();\r\n });\r\n };\r\n }\r\n}\r\n","import { IInputScope, KbInput } from \"@app/components/kb-input/kb-input.component\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { Utils } from \"@tools\";\r\n\r\nexport interface INumberboxScope extends IInputScope {\r\n /** see eFormatType: none, number, currency, percentage */\r\n format: string;\r\n minPrecision: number;\r\n maxPrecision: number;\r\n /** the currency iso code (only used if format = currency) */\r\n currency: string;\r\n thousandsSeparator: string;\r\n decimalSeparator: string;\r\n prefix: string;\r\n suffix: string;\r\n step: number;\r\n\r\n _formattedValue: string;\r\n}\r\n\r\n@NgComponent({\r\n token: Token.KbNumberbox,\r\n dependencies: [\r\n Token.$Timeout\r\n ]\r\n})\r\nexport class KbNumberbox extends KbInput {\r\n constructor(\r\n $timeout: ng.ITimeoutService\r\n ) {\r\n super($timeout);\r\n\r\n this.scope = Utils.extend(this.scope, {\r\n format: \"@\",\r\n minPrecision: \"@\",\r\n maxPrecision: \"@\",\r\n currency: \"@\",\r\n thousandsSeparator: \"@\",\r\n decimalSeparator: \"@\",\r\n prefix: \"@\",\r\n suffix: \"@\",\r\n step: \"@\"\r\n });\r\n\r\n this.template = Dirs.component(\"kb-numberbox\");\r\n\r\n this.link = (scope: INumberboxScope, element: ng.IAugmentedJQuery, atts: ng.IAttributes, controllers: any[]) => {\r\n this.kbInputLinkFn(scope, element, atts, controllers);\r\n\r\n scope.$watch(\"[ngModel,format,minPrecision,maxPrecision,currency,decimalSeparator,thousandsSeparator,prefix,suffix]\", () => {\r\n if (scope.ngModel != null && !isNaN(scope.ngModel)) {\r\n scope._formattedValue = (scope.ngModel as number).format({\r\n formatType: scope.format,\r\n minPrecision: Number(scope.minPrecision),\r\n maxPrecision: Number(scope.maxPrecision),\r\n currency: scope.currency,\r\n decimalSeparator: scope.decimalSeparator,\r\n thousandsSeparator: scope.thousandsSeparator,\r\n prefix: scope.prefix,\r\n suffix: scope.suffix\r\n });\r\n } else {\r\n scope._formattedValue = \"\";\r\n }\r\n });\r\n };\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { KbService } from \"@app/services/kb.service\";\r\n\r\n@NgComponent({\r\n token: Token.KbPageTitle,\r\n dependencies: [\r\n Token.KbService\r\n ]\r\n})\r\nexport class KbPageTitle extends Directive {\r\n constructor(\r\n private kbService: KbService\r\n ) {\r\n super();\r\n\r\n this.restrict = \"EA\";\r\n this.template = Dirs.component(\"kb-page-title\");\r\n this.transclude = true;\r\n this.scope = {\r\n icon: \"@\",\r\n label: \"@\",\r\n desc: \"@\",\r\n error: \"@\"\r\n };\r\n this.replace = true;\r\n this.link = (scope: any, element, atts) => {\r\n\r\n };\r\n }\r\n}\r\n","// tslint:disable:max-line-length\r\nimport { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { IConfiguratorScope } from \"@app/views/products/configurator.view\";\r\nimport { Configurator, Page } from \"@models\";\r\nimport * as angular from \"angular\";\r\n\r\ninterface IPageScope extends IConfiguratorScope {\r\n _page: Page;\r\n}\r\n\r\n@NgComponent({\r\n token: Token.KbPage,\r\n dependencies: [\r\n ]\r\n})\r\nexport class KbPage extends Directive {\r\n constructor() {\r\n super();\r\n\r\n this.replace = true;\r\n this.restrict = \"E\";\r\n this.scope = true;\r\n\r\n this.controller = [\r\n \"$scope\",\r\n \"$element\",\r\n \"$attrs\",\r\n \"$templateCache\",\r\n Token.$Compile.key,\r\n Token.$Http.key,\r\n \"$controller\",\r\n Token.$Timeout.key,\r\n \"$animate\",\r\n \"$transclude\",\r\n (\r\n $scope: IPageScope,\r\n $element: ng.IAugmentedJQuery,\r\n $attrs: ng.IAttributes,\r\n $templateCache: ng.ITemplateCacheService,\r\n $compile: ng.ICompileService,\r\n $http: ng.IHttpService,\r\n $controller: ng.IControllerService,\r\n $timeout: ng.ITimeoutService,\r\n $animate: ng.animate.IAnimateService,\r\n $transclude: ng.ITranscludeFunction) => {\r\n\r\n let pageDb: { [pageIden: string]: { scope: IPageScope; template?: ng.IAugmentedJQuery; } } = {};\r\n let oldTemplate: ng.IAugmentedJQuery;\r\n let newTemplate: ng.IAugmentedJQuery;\r\n let oldTemplateScope: IPageScope;\r\n let newTemplateScope: IPageScope;\r\n\r\n // because multiple instances of a nested configurator have the same page id, \r\n // we need to hash it with the configurator name\r\n let getPageIdentifier = (page: Page) => {\r\n return page.$parentConfigurator.name + \"-\" + page.id;\r\n };\r\n\r\n //cache the compiled template since it doesn't change\r\n let origTemplate = angular.element(Dirs.component(\"kb-page\"));\r\n let compiled = $compile(origTemplate);\r\n\r\n // pick the right properties page template\r\n let updateTemplate = () => {\r\n oldTemplate = newTemplate;\r\n oldTemplateScope = newTemplateScope;\r\n\r\n // if (oldTemplate) {\r\n // oldTemplate.removeClass(\"active\");\r\n // // $timeout(() => {\r\n // // oldTemplate.remove();\r\n // // if (oldTemplateScope) {\r\n // // oldTemplateScope.$destroy();\r\n // // oldTemplateScope = null;\r\n // // }\r\n // // }, 100);\r\n // }\r\n \r\n // create the new template\r\n if ($scope.selected && $scope.selected.page) {\r\n let pageIden = getPageIdentifier($scope.selected.page);\r\n if (pageDb[pageIden]) {\r\n newTemplate = pageDb[pageIden].template;\r\n newTemplateScope = pageDb[pageIden].scope;\r\n } else {\r\n // newTemplate = angular.element(Dirs.component(\"kb-page\"));\r\n // let compiled = $compile(newTemplate);\r\n newTemplateScope = $scope.$new() as IPageScope;\r\n compiled(newTemplateScope, (clonedElement, scope) => {\r\n clonedElement.addClass(\"kb-page-control__page--initializing\");\r\n $element.append(clonedElement);\r\n pageDb[pageIden] = {\r\n scope: newTemplateScope,\r\n template: clonedElement\r\n };\r\n newTemplate = clonedElement;\r\n });\r\n // add it to element\r\n // $element.append(newTemplate);\r\n\r\n \r\n }\r\n\r\n newTemplateScope._page = $scope.selected.page;\r\n //$timeout(() => newTemplate.addClass(\"active\"), 0);\r\n\r\n //$timeout(() => {\r\n let oldPage = oldTemplateScope ? oldTemplateScope._page : null;\r\n let newPage = newTemplateScope._page;\r\n let oldPageIndex = this.getHierarchicalIndex(oldPage);\r\n let newPageIndex = this.getHierarchicalIndex(newPage);\r\n let $oldPageEl = oldTemplate;\r\n let $newPageEl = newTemplate;\r\n\r\n $newPageEl.removeClass(\"kb-page-control__page--initializing\");\r\n newPage && $newPageEl.css(\"transition\", \"none\");\r\n if (this.isIndexGreater(newPageIndex, oldPageIndex)) {\r\n //oldPage && $oldPageEl.css(\"transform\", \"translate3d(-100%,0,0)\");\r\n newPage && $newPageEl.css(\"transform\", \"translate3d(100%,0,0)\");\r\n } else {\r\n newPage && $newPageEl.css(\"transform\", \"translate3d(-100%,0,0)\");\r\n }\r\n\r\n //if (newPage) newPage.selected = true;\r\n if (newTemplate) newTemplate.addClass(\"kb-page-control__page--selected\");\r\n\r\n setTimeout(() => {\r\n //animate the height also. \r\n // let currentHeight = oldPage && $oldPageEl.outerHeight();\r\n // newPage && $newPageEl.css(\"position\", \"relative\");\r\n // let newHeight = newPage && $newPageEl.outerHeight(); \r\n // newPage && $newPageEl.css(\"position\", \"absolute\");\r\n // $container.height(currentHeight);\r\n\r\n if (this.isIndexGreater(newPageIndex, oldPageIndex)) {\r\n oldPage && $oldPageEl.css(\"transform\", \"translate3d(-100%,0,0)\");\r\n } else {\r\n oldPage && $oldPageEl.css(\"transform\", \"translate3d(100%,0,0)\");\r\n }\r\n newPage && $newPageEl.css(\"transition\", \"\");\r\n newPage && $newPageEl.css(\"transform\", \"translate3d(0,0,0)\");\r\n\r\n // $container.height(newHeight);\r\n\r\n // $timeout(() => {\r\n // if (oldPage) oldPage.selected = false;\r\n // //on the first run the new tab element might not have existed until now, so we refresh the reference\r\n // $newPageEl = newTab && $element.find(`#tab-${newTab.$id}`);\r\n // newPage && $newPageEl.css(\"position\", \"relative\");\r\n // oldPage && $oldPageEl.css(\"position\", \"absolute\");\r\n\r\n // $container.height(\"auto\");\r\n // locked = false;\r\n // }, 300);\r\n\r\n setTimeout(() => {\r\n if (oldTemplate) oldTemplate.removeClass(\"kb-page-control__page--selected\");\r\n }, 300);\r\n }, 0);\r\n //});\r\n\r\n\r\n }\r\n };\r\n\r\n $scope.selected.pageChanged.add(args => {\r\n updateTemplate();\r\n });\r\n\r\n $scope.$on(\"$destroy\", () => {\r\n Object.keys(pageDb).forEach(key => {\r\n if (pageDb[key].scope) pageDb[key].scope.$destroy();\r\n });\r\n pageDb = null;\r\n });\r\n\r\n updateTemplate();\r\n }];\r\n }\r\n\r\n public getHierarchicalIndex(parent: Page | Configurator): number[] {\r\n let indexMap = [];\r\n \r\n while (parent && parent.$parent) {\r\n let index = 0;\r\n if (parent instanceof Page) {\r\n index = (parent.$parent as Page | Configurator).pages.indexOf(parent);\r\n } else if (parent instanceof Configurator) {\r\n index = (parent.$parent as Page | Configurator).configurators.indexOf(parent);\r\n } else {\r\n throw \"unexpected parent type\";\r\n }\r\n indexMap.unshift(index);\r\n parent = parent.$parent as Page | Configurator;\r\n }\r\n\r\n return indexMap;\r\n }\r\n\r\n public isIndexGreater(thisIndex: number[], otherIndex: number[]) {\r\n for (let i = 0; i < thisIndex.length; i++) {\r\n if (otherIndex.length == i) return true;\r\n if (thisIndex[i] < otherIndex[i]) return false;\r\n if (thisIndex[i] > otherIndex[i]) return true;\r\n }\r\n return false;\r\n }\r\n}\r\n","import { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { KbInput } from \"../kb-input/kb-input.component\";\r\n\r\n@NgComponent({\r\n token: Token.KbPassword,\r\n dependencies: [\r\n Token.$Timeout\r\n ]\r\n})\r\nexport class KbPassword extends KbInput {\r\n constructor($timeout: ng.ITimeoutService) {\r\n super($timeout);\r\n this.restrict = \"E\";\r\n this.replace = true;\r\n\r\n this.template = Dirs.component(\"kb-password\");\r\n\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\n@NgComponent({\r\n token: Token.KbPrivacyPolicy,\r\n dependencies: [\r\n Token.$Http\r\n ]\r\n})\r\nexport class KbPrivacyPolicy extends Directive {\r\n constructor($http: ng.IHttpService) {\r\n super();\r\n\r\n this.restrict = \"E\";\r\n this.replace = true;\r\n this.scope = {\r\n _html: \"=\"\r\n };\r\n this.template = Dirs.component(\"kb-privacy-policy\");\r\n\r\n this.link = (scope:any, element, atts) => {\r\n /*$http.get(\"/privacy.html\").then((d) => {\r\n scope._html = d.data;\r\n });*/\r\n };\r\n\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\n\r\n@NgComponent({\r\n token: Token.KbProgress,\r\n dependencies: [\r\n ]\r\n})\r\nexport class KbProgress extends Directive {\r\n constructor() {\r\n super();\r\n\r\n this.restrict = \"EA\";\r\n this.replace = true;\r\n this.scope = {\r\n animate: \"=\",\r\n type: \"@\",\r\n value: \"@\"\r\n };\r\n this.template = Dirs.component(\"kb-progress\");\r\n\r\n this.link = (scope, element, atts) => {\r\n\r\n };\r\n\r\n }\r\n}\r\n","import { IInputScope, KbInput } from \"@app/components/kb-input/kb-input.component\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { Utils } from \"@tools\";\r\n\r\nexport interface IRadioScope extends IInputScope {\r\n // external members\r\n source: any;\r\n valueField: string;\r\n labelField: string;\r\n /** custom data that can be passed in and accessed by the transcluded content for the select items */\r\n data: any;\r\n \r\n _id: string;\r\n _getItemValue: (item: any) => any;\r\n _select: (item: any) => void;\r\n _itemKeydown: (e: JQuery.Event, item: any) => void;\r\n}\r\n\r\nexport interface IRadioController {\r\n scope: IRadioScope;\r\n}\r\n\r\n@NgComponent({\r\n token: Token.KbRadio,\r\n dependencies: [\r\n Token.$Timeout,\r\n ]\r\n})\r\nexport class KbRadio extends KbInput {\r\n constructor(\r\n $timeout: ng.ITimeoutService\r\n ) {\r\n super($timeout);\r\n this.scope = Utils.extend(this.scope, {\r\n source: \"=\",\r\n valueField: \"@\",\r\n labelField: \"@\",\r\n data: \"=?\"\r\n });\r\n this.transclude = true;\r\n this.template = Dirs.component(\"kb-radio\");\r\n\r\n this.link = (scope: IRadioScope, element: JQuery, atts, controllers: any[]) => {\r\n this.kbInputLinkFn(scope, element, atts, controllers, false);\r\n let ngModel = controllers[0];\r\n\r\n scope._id = Utils.shortId();\r\n \r\n scope._getItemValue = (item: any) => {\r\n if (item === null || item === undefined) return null;\r\n return scope.valueField ? item[scope.valueField] : item;\r\n };\r\n scope._select = (item: any) => {\r\n if (!scope.ngDisabled) {\r\n ngModel.$setViewValue(scope._getItemValue(item));\r\n }\r\n };\r\n\r\n scope._itemKeydown = (e: JQuery.Event, item) => {\r\n if (e.key == 'Enter' || e.key == ' ' && !scope.ngDisabled) {\r\n scope._select(item);\r\n e.preventDefault();\r\n }\r\n else if (e.key == 'Escape') {\r\n // element.find(\"input\").blur();\r\n element.find(\".kb-radio__item\").trigger('blur');\r\n }\r\n };\r\n };\r\n }\r\n}","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\n\r\nexport interface IResizeScope extends ng.IScope {\r\n handles: string;\r\n containment: string;\r\n minWidth: string;\r\n maxWidth: string;\r\n minHeight: string;\r\n maxHeight: string;\r\n resizeDisabled: boolean;\r\n onStop: () => void;\r\n}\r\n\r\n@NgComponent({\r\n token: Token.KbResize,\r\n dependencies: [\r\n ]\r\n})\r\nexport class KbResize extends Directive {\r\n constructor() {\r\n super();\r\n\r\n this.restrict = \"E\";\r\n this.replace = true;\r\n this.transclude = true;\r\n this.scope = {\r\n handles: \"@\", // n, e, s, w, ne, se, sw, nw\r\n containment: \"@\", // parent or a selector for the element that constrains the size\r\n minWidth: \"@\",\r\n maxWidth: \"@\",\r\n minHeight: \"@\",\r\n maxHeight: \"@\",\r\n onStop: \"&\",\r\n resizeDisabled: \"=?\"\r\n };\r\n this.template = Dirs.component(\"kb-resize\");\r\n\r\n this.link = (scope: IResizeScope, elem: ng.IAugmentedJQuery, atts: ng.IAttributes) => {\r\n\r\n if (scope.minWidth) elem.css(\"min-width\", scope.minWidth);\r\n if (scope.maxWidth) elem.css(\"max-width\", scope.maxWidth);\r\n if (scope.minHeight) elem.css(\"min-height\", scope.minHeight);\r\n if (scope.maxHeight) elem.css(\"max-height\", scope.maxHeight);\r\n\r\n let exists = false;\r\n let createResizable = () => {\r\n elem.resizable({\r\n handles: scope.handles,\r\n containment: scope.containment || \"parent\",\r\n stop: () => {\r\n if (scope.onStop) scope.onStop();\r\n }\r\n } as any);\r\n exists = true;\r\n };\r\n let destroyResizable = () => {\r\n if (exists) elem.resizable(\"destroy\");\r\n exists = false; \r\n };\r\n\r\n // resizable doesn't handle flexbox well so we override the resize method for our own custom logic\r\n let resize = (event, ui) => {\r\n ui.position.left = ui.originalPosition.left;\r\n };\r\n\r\n elem.on(\"resize\", resize);\r\n\r\n scope.$watch(\"handles\", () => {\r\n if (exists) elem.resizable(\"option\", \"handles\", scope.handles);\r\n });\r\n\r\n scope.$watch(\"disabled\", () => {\r\n if (scope.resizeDisabled) {\r\n destroyResizable();\r\n } else {\r\n createResizable();\r\n }\r\n });\r\n\r\n scope.$on(\"$destroy\", () => {\r\n elem.off(\"resize\");\r\n destroyResizable();\r\n });\r\n };\r\n\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { IRootScope } from \"@models\";\r\n\r\n@NgComponent({\r\n token: Token.KbRipple,\r\n dependencies: [\r\n Token.$RootScope\r\n ]\r\n})\r\nexport class KbRipple extends Directive {\r\n constructor(\r\n $rootScope: IRootScope\r\n ) {\r\n super();\r\n\r\n this.restrict = \"A\";\r\n this.scope = false;\r\n\r\n this.link = (scope: ng.IScope, element, atts: any) => {\r\n let checkbox = scope.$eval(atts.kbRippleCheckbox);\r\n let $ripple: JQuery;\r\n let $wave: JQuery;\r\n let ripples: JQuery[] = [];\r\n let last: number;\r\n let duration = 300;\r\n if (!checkbox) {\r\n element.addClass(\"kb-ripple--hover\");\r\n }\r\n \r\n let rippleShow = (e: JQueryEventObject) => {\r\n let rippleDisabled = scope.$eval(atts.kbRippleDisabled) === true;\r\n if (!rippleDisabled) {\r\n if (element.closest(\"[disabled]\").length) {\r\n return;\r\n }\r\n\r\n let initPos = element.css(\"position\");\r\n let offset = element.offset();\r\n let elWidth = element[0].offsetWidth;\r\n let elHeight = element[0].offsetHeight;\r\n let dia = Math.max(elHeight, elWidth) * 2; // start diameter\r\n let x = checkbox ? \"50%\" : e.pageX - offset.left - (dia / 2) + \"px\";\r\n let y = checkbox ? \"50%\" : e.pageY - offset.top - (dia / 2) + \"px\";\r\n let scale = checkbox ? 2.88 : 1;\r\n $ripple = $('
', {\r\n class: \"kb-ripple\",\r\n appendTo: element,\r\n css: {\r\n overflow: checkbox ? \"visible\" : \"hidden\"\r\n }\r\n });\r\n ripples.push($ripple);\r\n \r\n if (!initPos || initPos === \"static\") {\r\n element.css({ position: \"relative\" });\r\n }\r\n\r\n $wave = $('
', {\r\n class: \"kb-ripple__wave kb-ripple__wave--enter kb-ripple__wave--visible\" + (checkbox ? \" kb-ripple__wave--checkbox\" : \"\"),\r\n css: {\r\n width: checkbox ? \"1.2rem\" : dia,\r\n height: checkbox ? \"1.2rem\" : dia,\r\n transform: `translate(${x}, ${y}) scale3d(0,0,0)`,\r\n marginLeft: checkbox ? \"-.6rem\" : 0,\r\n marginTop: checkbox ? \"-.6rem\" : 0\r\n },\r\n appendTo: $ripple,\r\n // one: {\r\n // animationend: function () {\r\n // $ripple.remove();\r\n // }\r\n // }\r\n });\r\n setTimeout(() => {\r\n $wave.removeClass(\"kb-ripple__wave--enter\");\r\n $wave.css(\"transform\", `translate(${x}, ${y}) scale3d(${scale}, ${scale}, ${scale})`);\r\n last = performance.now();\r\n }, 0);\r\n }\r\n };\r\n\r\n let rippleHide = () => {\r\n if (!element || !$ripple || !$wave) return;\r\n let delay = Math.max(duration - (performance.now() - last), 0);\r\n setTimeout(() => {\r\n $wave.removeClass(\"kb-ripple__wave--visible\");\r\n setTimeout(() => {\r\n ripples.forEach(r => r.remove());\r\n }, duration);\r\n }, delay); \r\n };\r\n\r\n element.on(\"pointerdown\", rippleShow);\r\n element.on('pointerup', rippleHide)\r\n element.on('pointerleave', rippleHide)\r\n element.on('dragstart', rippleHide)\r\n\r\n\r\n scope.$on(\"$destroy\", () => {\r\n element.off();\r\n });\r\n };\r\n\r\n }\r\n}","import { Directive } from \"@app/components/directive\";\r\nimport * as angular from \"angular\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\n/**\r\n * KbScope\r\n *\r\n * Allows you to create a new prototypically inherited scope on an element. Consider this example:\r\n *
\r\n * \r\n *
\r\n *\r\n * kbScope will put everything inside of the div into a new scope with the item property set on it\r\n * It accomplishes this by using transclusion\r\n */\r\n@NgComponent({\r\n token: Token.KbScope,\r\n dependencies: [\r\n ]\r\n})\r\nexport class KbScope extends Directive {\r\n constructor() {\r\n super();\r\n\r\n this.restrict = \"A\";\r\n this.scope = false;\r\n this.priority = 1000; // make sure it runs first\r\n this.transclude = \"element\";\r\n\r\n this.link = (scope, element: JQuery, atts: any, ctrl, $transclude) => {\r\n let childScope = scope.$new();\r\n scope.$watch(\"{\" + atts.kbScope + \"}\", data => {\r\n angular.extend(childScope, data);\r\n }, true);\r\n\r\n $transclude(childScope, clone => {\r\n element.after(clone);\r\n });\r\n\r\n scope.$on(\"$destroy\", () => {\r\n if (childScope) childScope.$destroy();\r\n });\r\n };\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { IColumnScope } from \"@app/components/kb-column/kb-column.component\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { ApiService } from \"@app/services/api.service\";\r\nimport { DrawerService } from \"@app/services/drawer.service\";\r\nimport { ISearchScope } from \"@app/views/search.view\";\r\n\r\nexport interface ISearchGridScope extends ISearchScope {\r\n scrollParent: string;\r\n drawerService: DrawerService;\r\n}\r\n \r\n@NgComponent({\r\n token: Token.KbSearchGrid,\r\n dependencies: [\r\n Token.DrawerService\r\n ]\r\n})\r\nexport class KbSearchGrid extends Directive {\r\n constructor(\r\n drawerService: DrawerService\r\n ) {\r\n\r\n super();\r\n\r\n this.template = Dirs.component(\"kb-search-grid\");\r\n this.restrict = \"AE\";\r\n this.scope = false;\r\n this.replace = true;\r\n this.transclude = {\r\n results: '?kbSearchGridResults',\r\n customResults: '?kbSearchGridCustomResults',\r\n toolbar: '?kbSearchGridToolbar'\r\n };\r\n\r\n this.controller = [\r\n \"$scope\",\r\n \"$element\",\r\n \"$attrs\",\r\n \"$transclude\",\r\n Token.ApiService.key,\r\n function(\r\n $scope: ISearchGridScope,\r\n $element: ng.IAugmentedJQuery,\r\n $attrs: ng.IAttributes,\r\n $transclude: ng.ITranscludeFunction,\r\n api: ApiService) {\r\n\r\n let columns: IColumnScope[] = $scope.columns = [];\r\n $scope.scrollParent = $attrs.scrollParent || \"#search-content\";\r\n $scope.drawerService = drawerService;\r\n\r\n let colDb = {};\r\n this.addColumn = (column: IColumnScope) => {\r\n if (!colDb[column.id]) {\r\n colDb[column.id] = column;\r\n \r\n columns.push(column);\r\n columns.sortBy(c => c.order);\r\n\r\n // column.$on(\"$destroy\", (event) => {\r\n // columns.remove(column);\r\n // });\r\n\r\n // set sort properties from query string \r\n if (column.field && column.field == $scope.binding.search.sortField) {\r\n column.sorted = true;\r\n column.descending = $scope.binding.search.descending;\r\n }\r\n }\r\n };\r\n\r\n }];\r\n }\r\n}\r\n","import { IInputScope, KbInput } from \"@app/components/kb-input/kb-input.component\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { SearchUtils, Utils } from \"@tools\";\r\nimport * as angular from \"angular\";\r\n\r\nexport interface ISelectScope extends IInputScope {\r\n // external members\r\n source: any;\r\n /** custom data that can be passed in and accessed by the transcluded content for the select items */\r\n data: any;\r\n valueField: string;\r\n labelField: string;\r\n defaultLabel: string;\r\n headerTemplate: string;\r\n mobileDropdown: boolean;\r\n /** if true, then a search box will be available in the dropdown */\r\n filter: boolean;\r\n itemStyle: any;\r\n optionLayout: string;\r\n /** for convenience when the consumer wants to have a custom headerTemplate, \r\n * they can bind to the selected data item \r\n */\r\n item: any;\r\n /** by default, kbSelect only watches for top level changes to the source array (like whether items are added or removed), but\r\n * doesn't watch the properties of items. To watch the properties also, set deepWatch to true.\r\n */\r\n deepWatch: boolean;\r\n \r\n\r\n // internal directive members\r\n _activeIndex: number;\r\n _selectedIndex: number;\r\n _select: (item: any) => void;\r\n _click: (e: JQueryEventObject) => void;\r\n _dropdownOpen: boolean;\r\n _selectedLabel: string;\r\n _queryChange: (e: ng.IAngularEvent) => void;\r\n _queryKeydown: (e: JQueryEventObject) => void;\r\n _id: string;\r\n _binding: { query: string };\r\n\r\n _filteredSource: any[];\r\n _isActive: (index) => boolean;\r\n _itemMousedown: (e: JQueryEventObject, item: any) => void;\r\n}\r\n\r\nexport interface ISelectController {\r\n scope: ISelectScope;\r\n}\r\n\r\n@NgComponent({\r\n token: Token.KbSelect,\r\n dependencies: [\r\n Token.$Timeout,\r\n Token.$Window,\r\n ]\r\n})\r\nexport class KbSelect extends KbInput {\r\n constructor(\r\n $timeout: ng.ITimeoutService,\r\n $window: ng.IWindowService\r\n ) {\r\n super($timeout);\r\n\r\n this.template = Dirs.component(\"kb-select\");\r\n this.scope = Utils.extend(this.scope, {\r\n source: \"=\",\r\n data: \"=?\",\r\n valueField: \"@\",\r\n labelField: \"@\",\r\n defaultLabel: \"@\",\r\n headerTemplate: \"@\",\r\n mobileDropdown: \"=?\",\r\n filter: \"=\",\r\n itemStyle: \"=?\",\r\n deepWatch: \"=?\",\r\n optionLayout: \"=?\"\r\n });\r\n this.transclude = true;\r\n\r\n this.compile = (element, atts: any) => {\r\n if (atts.mobileDropdown == null) atts.mobileDropdown = \"true\";\r\n return this.link;\r\n };\r\n\r\n this.controller = [\r\n \"$scope\",\r\n \"$element\",\r\n \"$attrs\",\r\n \"$transclude\",\r\n \"$templateCache\",\r\n Token.$Compile.key,\r\n function(\r\n $scope: ISelectScope,\r\n $element: ng.IAugmentedJQuery,\r\n $attrs: ng.IAttributes,\r\n $transclude: ng.ITranscludeFunction,\r\n $templateCache: ng.ITemplateCacheService,\r\n $compile: ng.ICompileService) {\r\n // set the scope on the controller so children can access it\r\n this.scope = $scope;\r\n \r\n // if a header template was passed in then get it from the template cache\r\n if ($scope.headerTemplate) {\r\n let $template = angular.element($templateCache.get($scope.headerTemplate));\r\n // compile the template\r\n let compiled = $compile($template, $transclude);\r\n // append it to the label\r\n $element.find(\".kb-select__header\").html(\"\").append($template);\r\n // now link it to the parent scope(we don't want this scope because it's an isolate scope)\r\n compiled($scope);\r\n }\r\n }];\r\n\r\n this.link = (scope: ISelectScope, element: JQuery, atts, controllers: any[]) => {\r\n // we provide out own implementation of isEmpty to kbInput since a value because null is an allowed value that could have a label\r\n // this is for material design so we know when to float the label\r\n let isEmpty = (val: any = null) => {\r\n return scope._selectedLabel == null || scope._selectedLabel.length == 0;\r\n };\r\n this.kbInputLinkFn(scope, element, atts, controllers, true, isEmpty);\r\n let ngModelCtrl = controllers[0];\r\n\r\n scope._id = Utils.shortId();\r\n scope._binding = { query: \"\" };\r\n let input = element.find(\"input\");\r\n // the source as an array (it might have been passed in as a function so we normalize it)\r\n let arraySource: any[];\r\n //readyForValue tracks wether a value has been chosen for the select list or not \r\n var readyForValue = false;\r\n\r\n let getItemValue = (item: any) => {\r\n if (item === null || item === undefined) return null;\r\n return scope.valueField ? item[scope.valueField] : item;\r\n };\r\n let getItemLabel = (item: any): string => {\r\n if (scope.labelField && item[scope.labelField] && item[scope.labelField]?.toString()) {\r\n return item[scope.labelField]?.toString();\r\n } else if (scope.valueField) {\r\n return item[scope.valueField];\r\n } else {\r\n return item;\r\n }\r\n };\r\n\r\n let updateSelectedLabel = () => {\r\n scope._selectedLabel = scope.item ? getItemLabel(scope.item) : scope.defaultLabel;\r\n };\r\n\r\n let isEnabled = () => {\r\n return !scope.ngDisabled;\r\n };\r\n\r\n let updateSelected = () => {\r\n if (arraySource) {\r\n for (let i = 0; i < arraySource.length; i++) {\r\n let item = arraySource[i];\r\n if (getItemValue(item) == ngModelCtrl.$viewValue) {\r\n scope.item = item;\r\n scope._selectedIndex = i;\r\n scope._activeIndex = i;\r\n updateSelectedLabel();\r\n scope._setHasValue(!isEmpty());\r\n return;\r\n }\r\n }\r\n }\r\n // if we get here, then it wasn't found.\r\n scope.item = null;\r\n updateSelectedLabel();\r\n scope._setHasValue(!isEmpty());\r\n };\r\n\r\n let showDropdown = () => {\r\n scope._dropdownOpen = true;\r\n readyForValue = true;\r\n \r\n // on mobile the filter input will kick off the keyboard, which we don't necessarily want. \r\n // The problem is worse on IOS because of focus restrictions\r\n if ($window.innerWidth >= Utils.MOBILE_WIDTH && !Utils.isIos()) {\r\n $timeout(() => input.trigger('focus'));\r\n\r\n if (scope.source.length > 10) {\r\n let searchBox = document.getElementById(scope._id + \"-input\");\r\n $timeout(() => searchBox.focus());\r\n }\r\n }\r\n };\r\n\r\n let hideDropdown = () => {\r\n scope._dropdownOpen = false;\r\n scope._binding.query = null;\r\n updateFilteredSource();\r\n };\r\n let toggleDropdown = () => {\r\n scope._dropdownOpen ? hideDropdown() : showDropdown();\r\n };\r\n\r\n // options might be added after the ngModel is set by the consumer, so\r\n // we need to refind the selected option \r\n let sourceChange = () => {\r\n if (angular.isFunction(scope.source)) {\r\n arraySource = scope.source();\r\n } else {\r\n arraySource = scope.source;\r\n }\r\n updateSelected();\r\n updateFilteredSource();\r\n }\r\n\r\n if (scope.deepWatch) {\r\n scope.$watch(\"source\", () => sourceChange(), true);\r\n } else {\r\n scope.$watchCollection(\"source\", () => sourceChange());\r\n }\r\n\r\n ngModelCtrl.$render = () => {\r\n updateSelected();\r\n };\r\n\r\n scope._itemMousedown = (e, item) => {\r\n e.preventDefault(); // so we don't lose focus\r\n scope._select(item);\r\n };\r\n\r\n scope._select = (item: any) => {\r\n if (readyForValue) {\r\n if (isEnabled()) {\r\n readyForValue = false;\r\n hideDropdown();\r\n ngModelCtrl.$setViewValue(getItemValue(item));\r\n updateSelected();\r\n }\r\n }\r\n };\r\n\r\n scope._click = e => {\r\n if (isEnabled()) {\r\n toggleDropdown();\r\n }\r\n };\r\n\r\n scope._isActive = index => {\r\n return index === scope._activeIndex;\r\n };\r\n\r\n let updateFilteredSource = () => {\r\n if (!scope._binding.query) {\r\n scope._filteredSource = arraySource;\r\n } else {\r\n scope._filteredSource = SearchUtils.search(\r\n scope._binding.query,\r\n arraySource,\r\n o => getItemLabel(o)?.toString(),\r\n 10000\r\n );\r\n scope._activeIndex = 0;\r\n }\r\n };\r\n\r\n scope._queryChange = e => {\r\n updateFilteredSource();\r\n };\r\n\r\n scope._queryKeydown = e => {\r\n if (e.key == \"ArrowUp\") {\r\n moveUp();\r\n e.stopPropagation();\r\n }\r\n if (e.key == \"ArrowDown\") {\r\n moveDown();\r\n e.stopPropagation();\r\n }\r\n if (e.key === \"Enter\") {\r\n enter();\r\n e.stopPropagation();\r\n }\r\n if (e.key === \"Tab\") {\r\n tab();\r\n if (scope._dropdownOpen) {\r\n e.stopPropagation();\r\n e.preventDefault();\r\n \r\n }\r\n }\r\n };\r\n\r\n let moveUp = () => {\r\n if (scope._dropdownOpen) {\r\n // if we are already at index zero, then close the dropdown\r\n let newIndex = scope._activeIndex - 1;\r\n if (newIndex >= 0) scope._activeIndex = newIndex;\r\n }\r\n };\r\n\r\n let moveDown = () => {\r\n showDropdown();\r\n // if we are already at index zero, then close the dropdown\r\n let newIndex = scope._activeIndex + 1;\r\n if (newIndex < scope._filteredSource.length) scope._activeIndex = newIndex;\r\n };\r\n \r\n let enter = () => {\r\n if (scope._dropdownOpen) {\r\n if (scope._filteredSource.length && scope._activeIndex > -1) {\r\n scope._select(scope._filteredSource[scope._activeIndex]);\r\n }\r\n element.trigger(\"focus\");\r\n } else {\r\n showDropdown();\r\n }\r\n };\r\n\r\n let tab = () => {\r\n if (scope._dropdownOpen) {\r\n element.trigger('focus');\r\n if (scope._filteredSource.length && scope._activeIndex > -1) {\r\n scope._select(scope._filteredSource[scope._activeIndex]);\r\n }\r\n }\r\n };\r\n\r\n let keySearch = (key) => {\r\n key = key.toLowerCase();\r\n let option = scope._activeIndex;\r\n let labelOrValue = scope._filteredSource[option].label?.toString() ?? scope._filteredSource[option].value;\r\n if (labelOrValue && !labelOrValue.toLowerCase().startsWith(key)) {\r\n\r\n option = scope._filteredSource.findIndex(a => {\r\n let b = a.label?.toString() || a.value;\r\n return b.toLowerCase().startsWith(key);\r\n });\r\n } else {\r\n if ((option + 1) < scope._filteredSource.length) {\r\n let optionPlusOne = scope._filteredSource[(option + 1)].label?.toString() ?? scope._filteredSource[(option + 1)].value;\r\n if (optionPlusOne && optionPlusOne.toLowerCase().startsWith(key)) {\r\n option++;\r\n } else {\r\n option = scope._filteredSource.findIndex(a => {\r\n let b = a.label?.toString() ?? a.value;\r\n return b.toLowerCase().startsWith(key);\r\n });\r\n }\r\n \r\n } else {\r\n option = scope._filteredSource.findIndex(a => {\r\n let b = a.label?.toString() ?? a.value;\r\n return b?.toLowerCase().startsWith(key);\r\n });\r\n }\r\n }\r\n if (option > -1) {\r\n showDropdown();\r\n scope._activeIndex = option;\r\n }\r\n \r\n };\r\n\r\n // bind keyboard events: arrows up(38) / down(40), enter(13) and tab(9), esc(27)\r\n element.on(\"keydown\", (e: JQuery.Event) => {\r\n switch (e.key) {\r\n case 'ArrowUp':\r\n e.preventDefault();\r\n scope.$apply(() => {\r\n moveUp();\r\n });\r\n break;\r\n case 'ArrowDown':\r\n e.preventDefault();\r\n scope.$apply(() => {\r\n moveDown();\r\n });\r\n break;\r\n case 'Enter':\r\n scope.$apply(() => {\r\n e.preventDefault();\r\n enter();\r\n });\r\n break;\r\n case 'Tab':\r\n scope.$apply(() => {\r\n if (scope._dropdownOpen) {\r\n e.stopPropagation();\r\n e.preventDefault();\r\n }\r\n tab();\r\n });\r\n break;\r\n case 'Escape':\r\n e.preventDefault();\r\n scope.$apply(() => {\r\n hideDropdown();\r\n e.stopPropagation();\r\n });\r\n element.trigger('blur');\r\n break;\r\n default:\r\n if (e.key.match(/^[a-zA-Z,0-9]+$/) && e.key.length == 1) {\r\n e.stopPropagation();\r\n e.preventDefault();\r\n scope.$apply(() => {\r\n keySearch(e.key);\r\n });\r\n }\r\n break;\r\n }\r\n });\r\n\r\n scope.$on(\"$destroy\", () => {\r\n element.off();\r\n });\r\n };\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { DrawerService } from \"@app/services/drawer.service\";\r\n\r\nexport interface ISfdcHeaderScope extends ng.IScope {\r\n drawerService: DrawerService;\r\n}\r\n\r\n@NgComponent({\r\n token: Token.KbSfdcHeader,\r\n dependencies: [\r\n Token.$Timeout,\r\n Token.DrawerService,\r\n ]\r\n})\r\nexport class KbSfdcHeader extends Directive {\r\n constructor(\r\n $timeout: ng.ITimeoutService,\r\n drawerService: DrawerService\r\n ) {\r\n super();\r\n\r\n this.restrict = \"EA\";\r\n this.template = Dirs.component(\"kb-sfdc-header\");\r\n this.scope = false;\r\n this.replace = true;\r\n\r\n this.controller = [\r\n \"$scope\",\r\n \"$element\",\r\n \"$attrs\",\r\n \"$transclude\",\r\n \"$templateCache\",\r\n Token.$Compile.key,\r\n function(\r\n $scope: ISfdcHeaderScope,\r\n $element: ng.IAugmentedJQuery,\r\n $attrs: ng.IAttributes,\r\n $transclude: ng.ITranscludeFunction,\r\n $templateCache: ng.ITemplateCacheService,\r\n $compile: ng.ICompileService) {\r\n // set the scope on the controller so children can access it\r\n this.scope = $scope;\r\n $scope.drawerService = drawerService;\r\n }];\r\n\r\n this.link = (scope: ISfdcHeaderScope, element: JQuery, atts, ngModel: ng.INgModelController) => {\r\n \r\n };\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport * as angular from \"angular\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\n@NgComponent({\r\n token: Token.KbSlide,\r\n dependencies: [\r\n ]\r\n})\r\nexport class KbSlide extends Directive {\r\n constructor() {\r\n super();\r\n\r\n this.restrict = \"EA\";\r\n this.replace = true;\r\n this.scope = {\r\n open: \"=\"\r\n };\r\n this.transclude = true;\r\n this.template = Dirs.component(\"kb-slide\");\r\n\r\n this.link = (scope: any, element, atts: any) => {\r\n // put a class on the body element in the form of\r\n // -visible so that other elements can react\r\n // to the slide being open\r\n if (atts.id) {\r\n let className = atts.id + \"-open\";\r\n scope.$watch(\"open\", newValue => {\r\n if (angular.isDefined(newValue)) {\r\n $(\"body\").toggleClass(className, newValue);\r\n }\r\n });\r\n }\r\n scope.clicked = () => {\r\n scope.open = false;\r\n };\r\n scope.$watch(\"open\", newValue => {\r\n if (!newValue) {\r\n $(element).find(\".kb-slide__nav\").scrollTop(0);\r\n }\r\n });\r\n };\r\n\r\n }\r\n}\r\n","import { IInputScope, KbInput } from \"@app/components/kb-input/kb-input.component\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { eFormatType, eSliderValueVisibility } from \"@models\";\r\nimport { Utils } from \"@tools\";\r\n\r\nexport interface ISliderScope extends IInputScope {\r\n min: number;\r\n max: number;\r\n step: number;\r\n directEdit?: boolean;\r\n valueVisibility?: eSliderValueVisibility;\r\n\r\n /** see eFormatType: none, number, currency, percentage */\r\n format: string;\r\n minPrecision: number;\r\n maxPrecision: number;\r\n /** the currency iso code (only used if format = currency) */\r\n currency: string;\r\n thousandsSeparator: string;\r\n decimalSeparator: string;\r\n prefix: string;\r\n suffix: string;\r\n\r\n currentVal?: number;\r\n dragging?: boolean; \r\n formattedValue?: string;\r\n tickPercent?: number; // the percentage step size that ticks will be shown\r\n lineClick?: (e: JQueryEventObject) => void;\r\n}\r\n@NgComponent({\r\n token: Token.KbSlider,\r\n dependencies: [\r\n Token.$Timeout,\r\n Token.$Document\r\n ]\r\n})\r\nexport class KbSlider extends KbInput {\r\n constructor(\r\n $timeout: ng.ITimeoutService,\r\n $document: ng.IDocumentService\r\n ) {\r\n super($timeout);\r\n\r\n this.scope = Utils.extend(this.scope, {\r\n min: \"=\",\r\n max: \"=\",\r\n step: \"=?\",\r\n format: \"@\",\r\n minPrecision: \"@\",\r\n maxPrecision: \"@\",\r\n currency: \"@\",\r\n thousandsSeparator: \"@\",\r\n decimalSeparator: \"@\",\r\n prefix: \"@\",\r\n suffix: \"@\",\r\n directEdit: \"=?\",\r\n valueVisibility: \"=?\"\r\n });\r\n\r\n this.template = Dirs.component(\"kb-slider\");\r\n\r\n this.link = (\r\n scope: ISliderScope,\r\n element: ng.IAugmentedJQuery,\r\n atts: ng.IAttributes,\r\n controllers: any[]\r\n ) => {\r\n this.kbInputLinkFn(scope, element, atts, controllers);\r\n let ngModel = controllers[0] as ng.INgModelController; \r\n let $thumb = element.find(\".kb-slider__thumb\");\r\n let thumbElem = $thumb[0];\r\n let lineElem = element.find(\".kb-slider__line\")[0];\r\n let valueLineElem = element.find(\".kb-slider__value-line\")[0];\r\n\r\n let setViewValue = (val) => {\r\n ngModel.$setViewValue(val);\r\n setFormattedValue(val);\r\n };\r\n\r\n let getNearestVal = (tryVal: number) => {\r\n let steps = Math.floor(scope.max / scope.step);\r\n let val = Math.round(tryVal / scope.step) * scope.step;\r\n val = Math.min(scope.max, Math.max(val, scope.min));\r\n return val;\r\n };\r\n\r\n let setCurrentValue = (val) => {\r\n scope.currentVal = val;\r\n return val;\r\n };\r\n \r\n let setThumbPos = (val, withAnimation = true) => {\r\n let clientWidth = lineElem.clientWidth;\r\n let percent = (val - scope.min) / (scope.max - scope.min);\r\n percent = Math.max(Math.min(1, percent), 0);\r\n let cssVal = `${percent * 100}%`;\r\n if (withAnimation) {\r\n $(thumbElem).stop(true, true).animate({ left: cssVal }, 300, \"easeInOutCubic\");\r\n $(valueLineElem).stop(true, true).animate({ width: cssVal }, 300, \"easeInOutCubic\");\r\n } else {\r\n thumbElem.style.left = cssVal;\r\n valueLineElem.style.width = cssVal;\r\n }\r\n \r\n return val;\r\n };\r\n\r\n let getValFromMousePos = (mouseClientX: number) => {\r\n let lineRect = lineElem.getBoundingClientRect();\r\n let lineWidth = lineRect.right - lineRect.left;\r\n let percent = (mouseClientX - lineRect.left) / lineWidth;\r\n let cval = ((scope.max - scope.min) * percent) + scope.min;\r\n cval = cval.rounder(scope.maxPrecision);\r\n cval = getNearestVal(cval);\r\n return cval;\r\n };\r\n\r\n let setFormattedValue = (value: any) => {\r\n let format = scope.format;\r\n if (!format || format == eFormatType.none) format = eFormatType.number;\r\n scope.formattedValue = (value as number).format({\r\n formatType: format,\r\n minPrecision: Number(scope.minPrecision),\r\n maxPrecision: Number(scope.maxPrecision),\r\n currency: scope.currency,\r\n decimalSeparator: scope.decimalSeparator,\r\n thousandsSeparator: scope.thousandsSeparator,\r\n prefix: scope.prefix,\r\n suffix: scope.suffix\r\n });\r\n return value;\r\n };\r\n\r\n let setTicks = (val) => {\r\n scope.tickPercent = Math.min(Math.max(scope.step / (scope.max - scope.min), .01), 1);\r\n return val;\r\n };\r\n\r\n //formatters are run in reverse\r\n ngModel.$formatters.push(setTicks);\r\n ngModel.$formatters.push(setFormattedValue);\r\n ngModel.$formatters.push(setThumbPos);\r\n ngModel.$formatters.push(setCurrentValue);\r\n ngModel.$formatters.push(getNearestVal);\r\n\r\n scope.lineClick = (e) => {\r\n if (!scope.ngDisabled) {\r\n let cval = getValFromMousePos(e.clientX);\r\n setCurrentValue(cval);\r\n setThumbPos(cval, true);\r\n setViewValue(cval);\r\n // scope.ngModel = cval; // set ngmodel instead of setViewValue so that it runs through all the formatters again\r\n }\r\n };\r\n\r\n let dragging = false;\r\n let pointerdown = (e: JQueryEventObject) => {\r\n if (!scope.ngDisabled) {\r\n scope.dragging = true;\r\n \r\n $document.attr(\"touch-action\", \"none\");\r\n $document.on(\"pointerup\", pointerup);\r\n $document.on(\"pointermove\", pointermove);\r\n\r\n scope.$digest();\r\n }\r\n };\r\n\r\n let pointerup = (e: JQueryEventObject) => {\r\n if (!scope.ngDisabled) {\r\n scope.dragging = false;\r\n $document.attr(\"touch-action\", \"\");\r\n $document.off(\"pointerup\", pointerup);\r\n $document.off(\"pointermove\", pointermove);\r\n\r\n setViewValue(scope.currentVal);\r\n scope.$digest();\r\n }\r\n };\r\n\r\n let pointermove = (e: JQueryEventObject) => {\r\n if (!scope.ngDisabled) {\r\n let cval = getValFromMousePos(e.clientX);\r\n scope.currentVal = cval;\r\n setThumbPos(cval, false);\r\n setFormattedValue(cval);\r\n scope.$digest();\r\n }\r\n }; \r\n\r\n let keydown = (e: JQueryEventObject) => {\r\n if (!scope.ngDisabled) {\r\n if (e.key == 'ArrowLeft') { //arrow left\r\n let cval = getNearestVal(scope.ngModel - scope.step);\r\n scope.currentVal = cval;\r\n setThumbPos(cval, false);\r\n setViewValue(cval);\r\n scope.$digest();\r\n } else if (e.key == 'ArrowRight') { //arrow right\r\n let cval = getNearestVal(scope.ngModel + scope.step);\r\n scope.currentVal = cval;\r\n setThumbPos(cval, false);\r\n setViewValue(cval);\r\n scope.$digest();\r\n } else if (e.key == 'Escape') {\r\n element.trigger('blur');\r\n }\r\n }\r\n };\r\n\r\n // we need to add the touch-action attribute to the svg element for the pep library\r\n // for the pointer-events w3c standard, this will be replaced by a css attribute\r\n $thumb.attr(\"touch-action\", \"none\");\r\n $thumb.on(\"pointerdown\", pointerdown);\r\n element.on(\"keydown\", keydown);\r\n \r\n scope.$watch(\"min\", (newVal) => {\r\n setThumbPos(scope.ngModel);\r\n setTicks(scope.ngModel);\r\n });\r\n scope.$watch(\"max\", (newVal) => {\r\n setThumbPos(scope.ngModel);\r\n setTicks(scope.ngModel);\r\n });\r\n scope.$watch(\"step\", (newVal) => {\r\n setThumbPos(scope.ngModel);\r\n setTicks(scope.ngModel);\r\n });\r\n\r\n scope.$on(\"$destroy\", () => {\r\n element.off();\r\n $document.off(\"pointerup\", pointerup);\r\n $document.off(\"pointermove\", pointermove);\r\n });\r\n };\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\n@NgComponent({\r\n token: Token.KbSpinnerElement,\r\n dependencies: [\r\n ]\r\n})\r\nexport class KbSpinnerElement extends Directive {\r\n constructor() {\r\n super();\r\n\r\n this.restrict = \"E\";\r\n this.scope = {\r\n tracker: \"=?\",\r\n show: \"=?\",\r\n label: \"=?\"\r\n };\r\n this.replace = true;\r\n\r\n this.template = \"
\" +\r\n \"
\" +\r\n \"
\" +\r\n \"
\" +\r\n \"
\" +\r\n \"
\" +\r\n \"
\" +\r\n \"
\" +\r\n \"
\" +\r\n \"
\" +\r\n \"
{{label}}
\" +\r\n \"
\";\r\n\r\n this.link = (scope: any, element, atts: any) => {\r\n // get the template\r\n\r\n };\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { IRootScope } from \"@models\";\r\n\r\n@NgComponent({\r\n token: Token.KbSpinner,\r\n dependencies: [\r\n Token.$Http,\r\n Token.$Compile,\r\n Token.$RootScope,\r\n ]\r\n})\r\nexport class KbSpinner extends Directive {\r\n constructor(\r\n private $http: ng.IHttpService,\r\n private $compile: ng.ICompileService,\r\n private $rootScope: IRootScope\r\n ) {\r\n super();\r\n\r\n this.restrict = \"A\";\r\n this.scope = true;\r\n\r\n this.link = (scope: any, element, atts: any) => {\r\n scope._tracker = scope.$eval(atts.kbSpinner);\r\n\r\n // get the template\r\n let template: string = \"
\" +\r\n \"
\" +\r\n \"
\" +\r\n \"
\" +\r\n \"
\" +\r\n \"
\" +\r\n \"
\" +\r\n \"
\" +\r\n \"
\" +\r\n \"
\" +\r\n \"
\";\r\n\r\n let templateElement = $compile(template)(scope);\r\n\r\n element.append(templateElement);\r\n };\r\n\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\n@NgComponent({\r\n token: Token.KbSrcOnError\r\n})\r\nexport class KbSrcOnError extends Directive {\r\n constructor() {\r\n super();\r\n this.restrict = \"A\";\r\n this.link = (scope, element: JQuery, atts, ctrl, $transclude) => {\r\n element.on('error', () => {\r\n element.attr('src', atts.kbSrcOnError);\r\n });\r\n };\r\n }\r\n}\r\n\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs, eBundle } from \"@app/helpers/dirs\";\r\n\r\nexport interface ISvgViewerScope extends ng.IScope {\r\n ngModel: string;\r\n _html: string;\r\n defs: string;\r\n height: number;\r\n width: number;\r\n /**\r\n * Mouse events provide means to customize behavior when dragging or clicking.\r\n * */\r\n kbDragStart: (obj: any) => void;\r\n kbDragEnd: (obj: any) => void;\r\n kbDragMove: (obj: any) => void;\r\n mouseWheel: (e: JQueryEventObject) => void;\r\n kbClick: (obj: any) => void;\r\n\r\n maxZoom: number;\r\n minZoom: number;\r\n disablePan: boolean;\r\n disableZoom: boolean;\r\n zoomLevel: number;\r\n panX: number;\r\n panY: number;\r\n\r\n svg: any;\r\n svgStyle: string;\r\n\r\n svgWidth: string;\r\n svgHeight: string;\r\n}\r\n/**\r\n * Given markdown text in the ngModel, will display the html\r\n */\r\n@NgComponent({\r\n token: Token.KbSvgViewer,\r\n dependencies: [\r\n Token.$Timeout\r\n ]\r\n})\r\nexport class KbSvgViewer extends Directive {\r\n constructor($timeout: ng.ITimeoutService) {\r\n super();\r\n this.scope = {\r\n ngModel: \"=\",\r\n width: \"=?\",\r\n height: \"=?\",\r\n svgWidth: \"=?\",\r\n svgHeight: \"=?\",\r\n svgStyle: \"=?\",\r\n kbDragStart: \"&\",\r\n kbDragMove: \"&\",\r\n kbDragEnd: \"&\",\r\n kbClick: \"&\",\r\n defs: \"=?\",\r\n maxZoom: \"=?\",\r\n minZoom: \"=?\",\r\n disablePan: \"=?\",\r\n disableZoom: \"=?\",\r\n zoomLevel: \"=?\",\r\n panX: \"=?\",\r\n panY: \"=?\"\r\n };\r\n\r\n this.restrict = \"E\";\r\n this.template = Dirs.component(\"kb-svg-viewer\", eBundle.app);\r\n this.replace = true;\r\n this.require = \"ngModel\";\r\n this.transclude = true;\r\n\r\n \r\n\r\n this.link = (scope: ISvgViewerScope, element: JQuery, atts, ngModel: ng.INgModelController) => {\r\n\r\n scope.svg = { width: \"0\", height: \"0\" };\r\n if (!scope.svgStyle) scope.svgStyle = \"\";\r\n\r\n if (!scope.minZoom) scope.minZoom = 0.124;\r\n if (!scope.maxZoom) scope.maxZoom = 4;\r\n if (!scope.zoomLevel) scope.zoomLevel = 1;\r\n if (!scope.panX) scope.panX = 0;\r\n if (!scope.panY) scope.panY = 0;\r\n\r\n const tolerance = 10;\r\n\r\n let isDown = false;\r\n let dragged = false;\r\n let dragOriginX = 0;\r\n let dragOriginY = 0;\r\n let baseMouse;\r\n\r\n let svg = element.find(\"svg\");\r\n let g = svg.find(\"g\");\r\n\r\n let svgDims = {\r\n width: 0,\r\n height: 0,\r\n scale: scope.zoomLevel,\r\n scrollX: scope.panX,\r\n scrollY: scope.panY\r\n };\r\n\r\n let svgWidthIsAuto = () => !scope.svgWidth || scope.svgWidth == \"auto\";\r\n\r\n let svgHeightIsAuto = () => !scope.svgHeight || scope.svgHeight == \"auto\";\r\n\r\n if (!svgWidthIsAuto()) {\r\n svgDims.width = parseFloat(scope.svgWidth);\r\n }\r\n if (!svgHeightIsAuto()) {\r\n svgDims.height = parseFloat(scope.svgHeight);\r\n }\r\n \r\n scope.$watch(\"zoomLevel\", (level: number) => {\r\n\r\n svgDims.scale = level;\r\n\r\n svgDims.scale = Math.min(Math.max(scope.minZoom, svgDims.scale), scope.maxZoom);\r\n\r\n updateSvg();\r\n });\r\n\r\n scope.$watch(\"panX\", (x: number) => {\r\n\r\n svgDims.scrollX = x;\r\n\r\n svgDims.scrollX = Math.min(Math.max(-svg.outerWidth() * svgDims.scale, svgDims.scrollX), svg.outerWidth() * svgDims.scale);\r\n\r\n updateSvg();\r\n });\r\n\r\n scope.$watch(\"panY\", (y: number) => {\r\n\r\n svgDims.scrollY = y;\r\n\r\n svgDims.scrollY = Math.min(Math.max(-svg.outerHeight() * svgDims.scale, svgDims.scrollY), svg.outerHeight() * svgDims.scale);\r\n\r\n updateSvg();\r\n });\r\n\r\n let getEvent = (e: MouseEvent) => {\r\n let svgWidth = svg.outerWidth();\r\n let svgHeight = svg.outerHeight();\r\n\r\n let modifierX = svgDims.width / svgWidth;\r\n let modifierY = svgDims.height / svgHeight;\r\n\r\n let event = {\r\n offsetX: e.offsetX * modifierX + svgDims.scrollX * modifierX,\r\n offsetY: e.offsetY * modifierY + svgDims.scrollY * modifierY,\r\n target: e.target,\r\n currentTarget: e.currentTarget\r\n }\r\n return event;\r\n };\r\n\r\n let updateSvg = (recalculateSize: boolean = true) => {\r\n\r\n if (recalculateSize) {\r\n if (svgWidthIsAuto()) {\r\n svgDims.width = 0;\r\n }\r\n else {\r\n svgDims.width = (parseInt(scope.svgWidth));\r\n }\r\n if (svgHeightIsAuto()) {\r\n svgDims.height = 0;\r\n }\r\n else {\r\n svgDims.height = (parseInt(scope.svgHeight));\r\n }\r\n\r\n g.children().each(function () {\r\n let thisEl = (jQuery(this)[0]);\r\n if (thisEl.getBBox) {\r\n let bbox = thisEl.getBBox();\r\n let xPos = (bbox.x + bbox.width);\r\n let yPos = (bbox.y + bbox.height);\r\n\r\n if (svgWidthIsAuto()) {\r\n if (xPos > svgDims.width) svgDims.width = xPos;\r\n }\r\n if (svgHeightIsAuto()) {\r\n if (yPos > svgDims.height) svgDims.height = yPos;\r\n }\r\n }\r\n });\r\n }\r\n\r\n scope.svg.width = svgDims.width * svgDims.scale;\r\n scope.svg.height = svgDims.height * svgDims.scale;\r\n\r\n let render = () => {\r\n g.attr(\"transform\", `scale(${svgDims.scale}, ${svgDims.scale})`);\r\n //element.scrollLeft(svgDims.scrollX);\r\n //element.scrollTop(svgDims.scrollY);\r\n\r\n let svgWidth = svg.outerWidth();\r\n let svgHeight = svg.outerHeight();\r\n\r\n let modifierX = svgDims.width / svgWidth;\r\n let modifierY = svgDims.height / svgHeight;\r\n\r\n let viewBoxX = (svgDims.scrollX * modifierX);\r\n let viewBoxY = (svgDims.scrollY * modifierY);\r\n\r\n if (!isNaN(viewBoxX) && !isNaN(viewBoxY)) {\r\n svg.attr(\"viewBox\", viewBoxX + \" \" + viewBoxY + \" \" + svgDims.width + \" \" + svgDims.height);\r\n }\r\n };\r\n\r\n render();\r\n if (recalculateSize) {\r\n render();\r\n }\r\n\r\n $timeout(() => scope.$digest());\r\n }\r\n\r\n let onMousedown = (e: PointerEvent) => {\r\n isDown = true;\r\n scope.kbDragStart({ $event: getEvent(e) });\r\n baseMouse = {\r\n x: e.screenX + svgDims.scrollX,\r\n y: e.screenY + svgDims.scrollY\r\n };\r\n };\r\n\r\n let onMouseup = (e: PointerEvent) => {\r\n scope.kbDragEnd({ $event: getEvent(e) });\r\n if (!dragged) {\r\n\r\n let inSvg = false;\r\n let el = (e.target);\r\n while (el) {\r\n if (el.tagName == \"svg\") {\r\n inSvg = true;\r\n break;\r\n }\r\n el = el.parentElement;\r\n }\r\n\r\n if (inSvg) {\r\n scope.kbClick({ $event: getEvent(e) });\r\n e.preventDefault();\r\n e.stopPropagation();\r\n }\r\n }\r\n else {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n }\r\n isDown = dragged = false;\r\n };\r\n\r\n let onMousemove = (e: PointerEvent) => {\r\n if (isDown) {\r\n scope.kbDragMove({ $event: getEvent(e) });\r\n if (!scope.disablePan) {\r\n scope.panX = svgDims.scrollX = (baseMouse.x - e.screenX);\r\n scope.panY = svgDims.scrollY = (baseMouse.y - e.screenY);\r\n updateSvg(false);\r\n }\r\n let diff = Math.sqrt(Math.abs(((baseMouse.x - e.screenX) ^ 2) + ((baseMouse.y - e.screenY) ^ 2)));\r\n if (diff > tolerance) dragged = true;\r\n }\r\n };\r\n\r\n let onWheel = (event: WheelEvent) => {\r\n event.preventDefault();\r\n\r\n if (scope.disableZoom) return;\r\n\r\n let difference = 1;\r\n if (event.deltaY < 0) {\r\n difference = 1.05;\r\n }\r\n else {\r\n difference = 0.95;\r\n }\r\n\r\n let oldZoom = svgDims.scale;\r\n\r\n svgDims.scale *= difference;\r\n scope.zoomLevel = svgDims.scale;\r\n\r\n svgDims.scale = Math.min(Math.max(scope.minZoom, svgDims.scale), scope.maxZoom);\r\n\r\n let zoom = svgDims.scale;\r\n\r\n let scalechange = zoom - oldZoom;\r\n\r\n scope.panX = svgDims.scrollX = svgDims.scrollX + (event.offsetX * scalechange);\r\n scope.panY = svgDims.scrollY = svgDims.scrollY + (event.offsetY * scalechange);\r\n\r\n //window.console.log(svgDims.scrollX + \", \" + svgDims.scrollY);\r\n\r\n updateSvg(false);\r\n };\r\n\r\n ngModel.$render = () => { // called when the binding has been changed by the consumer\r\n let v:string = ngModel.$viewValue;\r\n if (!v) v = \"\";\r\n v = v.replace(/url\\((#[^\\)]*)\\)/g, \"url(\" + location.href + \"$1)\");\r\n scope._html = v;// $v[0].innerHTML;// v? md.Transform(v): null;\r\n\r\n setTimeout(updateSvg, 1);\r\n };\r\n\r\n element[0].addEventListener(\"pointerdown\", onMousedown);\r\n document.addEventListener(\"pointerup\", onMouseup);\r\n element[0].addEventListener(\"pointermove\", onMousemove);\r\n element[0].addEventListener(\"wheel\", onWheel);\r\n\r\n scope.$on(\"$destroy\", () => {\r\n element[0].removeEventListener(\"pointerdown\", onMousedown);\r\n document.removeEventListener(\"pointerup\", onMouseup);\r\n element[0].removeEventListener(\"pointermove\", onMousemove);\r\n element[0].removeEventListener(\"wheel\", onWheel);\r\n });\r\n };\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { ITabsController, ITabsScope } from \"@app/components/kb-tabs/kb-tabs.component\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { IAugmentedJQuery } from \"angular\";\r\n\r\nexport interface ITabScope extends ng.IScope {\r\n value: any;\r\n label: string;\r\n invalid: boolean;\r\n selected: boolean;\r\n visible: boolean;\r\n icon: string;\r\n image: string;\r\n imageWhenSelected: string;\r\n\r\n _tabsScope: ITabsScope;\r\n _getElement: () => IAugmentedJQuery;\r\n}\r\n\r\n@NgComponent({\r\n token: Token.KbTab,\r\n dependencies: [\r\n ]\r\n})\r\nexport class KbTab extends Directive {\r\n constructor() {\r\n super();\r\n\r\n this.require = \"^kbTabs\";\r\n this.replace = true;\r\n this.template = Dirs.component(\"kb-tab\");\r\n this.restrict = \"AE\";\r\n this.scope = {\r\n value: \"=\",\r\n label: \"@\",\r\n invalid: \"=?\",\r\n selected: \"=?\",\r\n visible: \"=?\",\r\n icon: \"@\",\r\n image: \"@\",\r\n imageWhenSelected: \"@\"\r\n };\r\n this.transclude = true;\r\n\r\n this.compile = (element, atts: any) => {\r\n if (atts.visible == null) atts.visible = \"true\";\r\n return this.link;\r\n };\r\n\r\n this.link = (scope: ITabScope, element, atts: any, tabsCtrl: ITabsController) => {\r\n scope._getElement = () => {\r\n return element;\r\n };\r\n scope._tabsScope = tabsCtrl.scope;\r\n tabsCtrl.registerTab(scope);\r\n\r\n scope.$watch(\"visible\", () => tabsCtrl.tabVisibleChanged(scope));\r\n };\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { ITabScope } from \"@app/components/kb-tabs/kb-tab.component\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\n\r\nexport interface ITabsScope extends ng.IScope {\r\n /** 2 way binding that holds the value of the currently selected tab */\r\n selectedTab: string;\r\n /** event fires when the selected tab has changed. Has signature of: (oldTab: string, newTab: string) => void; */\r\n tabChanged: any; \r\n /** aligns with eTabWidth enum */\r\n tabWidth: string;\r\n /** sets the width of tab header if tabWidth is set to 'custom' */\r\n customTabWidth: number;\r\n /** the actual selected kbTab scope */\r\n _selectedTabScope: ITabScope;\r\n _tabs: ITabScope[];\r\n _select: (tab: ITabScope) => void;\r\n _lineLeft: number;\r\n _lineWidth: number;\r\n _headerClick: (e: JQueryEventObject, tab: ITabScope) => void;\r\n _paged: boolean;\r\n _scrollNext: () => void;\r\n _scrollPrev: () => void;\r\n _pageNextVisible: boolean;\r\n _pagePrevVisible: boolean;\r\n}\r\n\r\nexport interface ITabsController {\r\n scope: ITabsScope;\r\n registerTab: (tab: ITabScope) => void;\r\n tabVisibleChanged: (tab: ITabScope) => void;\r\n}\r\n\r\n/**\r\n * kbTabs\r\n *\r\n * kbTabs is utilized by having a parent kb-tabs element, and inside of it a kb-tab-pane (which are the headers)\r\n * and many kb-tab directives. You can place the kb-tabs-pane and the kb-tabs wherever you like, as long as they\r\n * are inside the kb-tabs directive. This gives a flexible approach which we can use in any situation.\r\n * \r\n * \r\n * \r\n * \r\n * \r\n * \r\n *\r\n * you can remotely control the selected tab by using a two-way binding with selectedTab scope property. This\r\n * property is looking for the name of the tab. \r\n *\r\n */\r\n\r\n@NgComponent({\r\n token: Token.KbTabs,\r\n dependencies: [\r\n Token.$Timeout,\r\n Token.$Window\r\n ]\r\n})\r\nexport class KbTabs extends Directive {\r\n constructor($timeout: ng.ITimeoutService, $window: ng.IWindowService) {\r\n\r\n super();\r\n\r\n this.replace = true;\r\n this.template = Dirs.component(\"kb-tabs\");\r\n this.restrict = \"AE\";\r\n this.scope = {\r\n selectedTab: \"=?\",\r\n tabChanged: \"&\",\r\n tabWidth: \"=?\",\r\n customTabWidth: \"=?\"\r\n };\r\n this.transclude = true;\r\n\r\n // add scope defaults to the compile function\r\n this.compile = (element, atts: any) => {\r\n\r\n };\r\n\r\n this.controller = [\r\n \"$scope\",\r\n \"$element\",\r\n \"$attrs\",\r\n \"$transclude\",\r\n function(\r\n $scope: ITabsScope,\r\n $element: ng.IAugmentedJQuery,\r\n $attrs: ng.IAttributes,\r\n $transclude: ng.ITranscludeFunction) {\r\n\r\n // set the scope of the tree on it's controller so children can access it\r\n this.scope = $scope;\r\n let locked = false; //during tab animations we lock the user from switching tabs\r\n let firstRun = true;\r\n let scrollLeft: number = 0;\r\n $scope._tabs = [];\r\n let $container = $element.find(\".kb-tabs__tab-container\");\r\n let $headers = $element.find(\".kb-tabs__headers\");\r\n let $pane = $element.find(\".kb-tabs__pane\");\r\n let $headersContainer = $element.find(\".kb-tabs__headers-container\");\r\n let selectionLineEl = $element.find(\".kb-tabs__selection-line\")[0];\r\n\r\n $scope._select = tab => {\r\n $scope.selectedTab = tab.value;\r\n };\r\n $scope._headerClick = (e, tab) => {\r\n if (!locked) {\r\n $scope._select(tab);\r\n } \r\n }\r\n\r\n let setSelectedTabScope = (tab: ITabScope) => {\r\n let oldTab = $scope._selectedTabScope;\r\n let newTab = tab;\r\n\r\n $scope._selectedTabScope = tab;\r\n\r\n if (oldTab !== newTab) {\r\n firstRun ? $timeout(() => positionSelectionLine(tab), 0) : positionSelectionLine(tab);\r\n scrollSelectedIntoView();\r\n animateContent(oldTab, newTab);\r\n if (!firstRun && $scope.tabChanged) { //for the first run, we are just selecting the first visible tab. This should not count as a tabChanged event\r\n firstRun = false;\r\n $scope.tabChanged({ oldTab: oldTab ? oldTab.value : null, newTab: newTab ? newTab.value : null });\r\n }\r\n firstRun = false;\r\n \r\n } \r\n };\r\n\r\n let positionSelectionLine = (tab: ITabScope) => {\r\n let headerEl = $element.find(`#${tab.$id}`)[0];\r\n \r\n if (headerEl) {\r\n selectionLineEl.style.left = headerEl.offsetLeft + \"px\";\r\n selectionLineEl.style.width = headerEl.offsetWidth + \"px\";\r\n } \r\n };\r\n\r\n let animateContent = (oldTab: ITabScope, newTab: ITabScope) => {\r\n locked = true;\r\n let oldTabIndex = $scope._tabs.indexOf(oldTab);\r\n let newTabIndex = $scope._tabs.indexOf(newTab);\r\n let $oldTabEl = oldTab && oldTab._getElement();\r\n let $newTabEl = newTab && newTab._getElement();\r\n\r\n let oldTabClass: string;\r\n let newTabClass: string;\r\n newTab && $newTabEl.css(\"transition\", \"none\");\r\n if (newTabIndex > oldTabIndex) {\r\n //oldTab && $oldTabEl.css(\"transform\", \"translate3d(-100%,0,0)\");\r\n newTab && $newTabEl.css(\"transform\", \"translate3d(100%,0,0)\"); \r\n } else {\r\n newTab && $newTabEl.css(\"transform\", \"translate3d(-100%,0,0)\");\r\n }\r\n\r\n if (newTab) newTab.selected = true; \r\n \r\n\r\n setTimeout(() => {\r\n //animate the height also. \r\n let currentHeight = oldTab && $oldTabEl.outerHeight();\r\n newTab && $newTabEl.css(\"position\", \"relative\");\r\n // oldTab && $oldTabEl.css(\"position\", \"absolute\");\r\n // $container.height(\"auto\");\r\n let newHeight = newTab && $newTabEl.outerHeight(); // $container[0].offsetHeight;\r\n newTab && $newTabEl.css(\"position\", \"absolute\");\r\n // oldTab && $oldTabEl.css(\"position\", \"relative\");\r\n $container.height(currentHeight);\r\n\r\n if (newTabIndex > oldTabIndex) {\r\n oldTab && $oldTabEl.css(\"transform\", \"translate3d(-100%,0,0)\");\r\n } else {\r\n oldTab && $oldTabEl.css(\"transform\", \"translate3d(100%,0,0)\");\r\n }\r\n newTab && $newTabEl.css(\"transition\", \"\");\r\n newTab && $newTabEl.css(\"transform\", \"translate3d(0,0,0)\");\r\n\r\n $container.height(newHeight);\r\n\r\n // $timeout(() => {\r\n \r\n // }, 0);\r\n\r\n $timeout(() => {\r\n if (oldTab) oldTab.selected = false;\r\n //on the first run the new tab element might not have existed until now, so we refresh the reference\r\n $newTabEl = newTab && $element.find(`#tab-${newTab.$id}`);\r\n newTab && $newTabEl.css(\"position\", \"relative\");\r\n oldTab && $oldTabEl.css(\"position\", \"absolute\");\r\n\r\n $container.height(\"auto\");\r\n locked = false;\r\n }, 300);\r\n }, 0);\r\n };\r\n\r\n \r\n \r\n // all child nodes register themselves with the tree to handle selection and accordion functionality\r\n this.registerTab = (tab: ITabScope) => {\r\n $scope._tabs.push(tab);\r\n tab.$on(\"$destroy\", event => {\r\n $scope._tabs.remove(tab);\r\n\r\n let selectedTab = $scope._tabs.find(t => t.selected);\r\n if (selectedTab) {\r\n $scope._select(selectedTab);\r\n $timeout(() => positionSelectionLine(selectedTab), 0);\r\n }\r\n\r\n });\r\n updateSelectedTabScope();\r\n };\r\n\r\n this.tabVisibleChanged = (tab: ITabScope) => {\r\n //if the selected tab isn't visible then select the first visible one\r\n if (tab.selected && !tab.visible) {\r\n $scope.selectedTab = null;\r\n $timeout(() => {\r\n updateSelectedTabScope();\r\n });\r\n } else {\r\n $timeout(() => {\r\n if ($scope._selectedTabScope) positionSelectionLine($scope._selectedTabScope);\r\n });\r\n }\r\n };\r\n\r\n let updateSelectedTabScope = () => {\r\n if (!$scope.selectedTab && $scope._tabs.some(t => t.visible)) {\r\n $scope.selectedTab = $scope._tabs.find(t => t.visible).value;\r\n }\r\n for (let tab of $scope._tabs) {\r\n if (tab.value === $scope.selectedTab) {\r\n setSelectedTabScope(tab);\r\n break;\r\n }\r\n } \r\n };\r\n // if the consumer changes the selected item, we update the selected node\r\n $scope.$watch(\"selectedTab\", (newVal, oldVal) => {\r\n updateSelectedTabScope();\r\n });\r\n $scope.$watch(\"tabWidth\", () => {\r\n if ($scope._selectedTabScope) $timeout(() => positionSelectionLine($scope._selectedTabScope), 300);\r\n });\r\n $scope.$watch(\"customTabWidth\", () => {\r\n if ($scope._selectedTabScope) $timeout(() => positionSelectionLine($scope._selectedTabScope), 300);\r\n });\r\n\r\n let updatePagination = () => {\r\n let containerWidth = $headersContainer.width();\r\n let headersWidth = $headers.width();\r\n let paneWidth = $pane.width();\r\n $scope._paged = (headersWidth > paneWidth);\r\n $scope._pageNextVisible = (headersWidth > containerWidth + scrollLeft);\r\n $scope._pagePrevVisible = (scrollLeft > 0);\r\n };\r\n\r\n let scrollSelectedIntoView = () => {\r\n let headerEl = $element.find(`#${$scope._selectedTabScope.$id}`)[0];\r\n if (headerEl) {\r\n let elemLeft = headerEl.offsetLeft;\r\n let elemRight = elemLeft + headerEl.offsetWidth;\r\n let containerWidth = $headersContainer[0].clientWidth;\r\n\r\n if (elemLeft - scrollLeft < 0) {\r\n setScroll(elemLeft);\r\n } else if (elemRight > scrollLeft + containerWidth) {\r\n setScroll(elemRight - containerWidth);\r\n }\r\n }\r\n };\r\n\r\n $scope._scrollNext = () => {\r\n setScroll(scrollLeft + $headersContainer.width());\r\n };\r\n\r\n $scope._scrollPrev = () => {\r\n setScroll(scrollLeft - $headersContainer.width());\r\n };\r\n\r\n let setScroll = (val: number) => {\r\n scrollLeft = fixScroll(val);\r\n $headers.css(\"transform\", `translateX(${-scrollLeft}px)`);\r\n updatePagination();\r\n };\r\n\r\n let scroll = (e: JQueryEventObject) => {\r\n if ($scope._paged) {\r\n e.preventDefault();\r\n setScroll(scrollLeft - (e as any).wheelDelta);\r\n $scope.$digest();\r\n }\r\n };\r\n\r\n let fixScroll = (value: number): number => {\r\n if (!$scope._paged) return 0;\r\n if (value < 0) return 0;\r\n let headersWidth = $headers.width();\r\n let containerWidth = $headersContainer.width();\r\n\r\n if (value > headersWidth - containerWidth) return headersWidth - containerWidth; \r\n return value;\r\n };\r\n\r\n let windowResize = (e: JQueryEventObject) => {\r\n updatePagination();\r\n setScroll(scrollLeft);\r\n $scope.$digest();\r\n };\r\n\r\n $headersContainer[0].addEventListener(\"mousewheel\", scroll);\r\n $($window).on(\"resize\", windowResize);\r\n\r\n\r\n $timeout(() => {\r\n updatePagination();\r\n }, 0);\r\n\r\n $scope.$on(\"$destroy\", () => {\r\n if ($headers && $headers.length) $headers[0].removeEventListener(\"mousewheel\", scroll);\r\n $($window).off(\"resize\", windowResize);\r\n });\r\n }];\r\n }\r\n}\r\n","import { IInputScope, KbInput } from \"@app/components/kb-input/kb-input.component\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { eMaskType } from \"@models\";\r\nimport { Utils } from \"@tools\";\r\n\r\nexport interface ITextboxScope extends IInputScope {\r\n mask?: string; // \r\n _maskConfig?: {};\r\n}\r\n\r\n@NgComponent({\r\n token: Token.KbTextbox,\r\n dependencies: [\r\n Token.$Timeout\r\n ]\r\n})\r\nexport class KbTextbox extends KbInput {\r\n constructor($timeout: ng.ITimeoutService) {\r\n super($timeout);\r\n this.scope = Utils.extend(this.scope, {\r\n mask: \"=?\"\r\n });\r\n this.template = Dirs.component(\"kb-textbox\");\r\n this.controller = [\r\n \"$scope\",\r\n \"$element\",\r\n \"$attrs\",\r\n function (\r\n $scope: ITextboxScope,\r\n $element: ng.IAugmentedJQuery,\r\n $attrs: ng.IAttributes) {\r\n \r\n $scope._maskConfig = {\r\n mask: () => {\r\n switch ($scope.mask) {\r\n case eMaskType.phone:\r\n return ['(', /[1-9]/, /\\d/, /\\d/, ')', ' ', /\\d/, /\\d/, /\\d/, '-', /\\d/, /\\d/, /\\d/, /\\d/];\r\n case eMaskType.zipCode:\r\n return [/\\d/, /\\d/, /\\d/, /\\d/, /\\d/];\r\n default:\r\n return false;\r\n }\r\n },\r\n placeholderChar: '\\u2000',\r\n guide: true,\r\n keepCharPositions: false,\r\n showMask: false\r\n };\r\n }];\r\n this.link = (scope: ITextboxScope, element: ng.IAugmentedJQuery, atts: ng.IAttributes, controllers: any[]) => {\r\n this.kbInputLinkFn(scope, element, atts, controllers);\r\n\r\n //need to fully blur field on ESC press\r\n element.on(\"keydown\", (e: JQuery.Event) => {\r\n if (e.key == 'Escape') {\r\n element.find(\"input\").trigger('blur');\r\n element.find(\"textarea\").trigger('blur');\r\n }\r\n });\r\n };\r\n }\r\n}\r\n","import { KbTextbox } from \"@app/components/kb-textbox/kb-textbox.component\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\n\r\n@NgComponent({\r\n token: Token.KbTextarea,\r\n dependencies: [\r\n Token.$Timeout\r\n ]\r\n})\r\nexport class KbTextarea extends KbTextbox {\r\n constructor($timeout: ng.ITimeoutService) {\r\n super($timeout);\r\n this.restrict = \"E\";\r\n this.replace = true;\r\n\r\n this.template = Dirs.component(\"kb-textarea\");\r\n }\r\n}\r\n","import { KbCheckbox } from \"@app/components/kb-checkbox/kb-checkbox.component\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\n\r\ninterface IToggleScope extends ng.IScope {\r\n ngModel?: any;\r\n ngDisabled?: boolean;\r\n inputId?: string;\r\n ngChange?: () => void;\r\n _ngChange: () => void;\r\n}\r\n\r\n@NgComponent({\r\n token: Token.KbToggle,\r\n dependencies: [\r\n Token.$Timeout\r\n ]\r\n})\r\nexport class KbToggle extends KbCheckbox {\r\n constructor($timeout: ng.ITimeoutService) {\r\n super($timeout);\r\n \r\n this.template = Dirs.component(\"kb-toggle\");\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\n\r\ninterface ITooltipScope extends ng.IScope {\r\n label?: string;\r\n media?: string;\r\n helpUrl?: string;\r\n desc?: string;\r\n\r\n _close?: () => void;\r\n}\r\n\r\n@NgComponent({\r\n token: Token.KbTooltip,\r\n dependencies: [\r\n Token.$Timeout\r\n ]\r\n})\r\nexport class KbTooltip extends Directive {\r\n constructor(\r\n $timeout: ng.ITimeoutService\r\n ) {\r\n super();\r\n\r\n this.restrict = \"EA\";\r\n this.scope = {\r\n label: \"=?\",\r\n media: \"=?\",\r\n helpUrl: \"=?\",\r\n desc: \"=?\"\r\n };\r\n this.replace = true;\r\n this.transclude = true;\r\n this.template = Dirs.component(\"kb-tooltip\");\r\n \r\n this.link = (scope: ITooltipScope, element: JQuery, atts: any) => {\r\n \r\n };\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\n/**\r\n * kbTransclude\r\n *\r\n * This is an alternative to ngTransclude, which allows you to select which \r\n * scope the transcluded content in the directive should have.\r\n * This is usefule because the standard ngTransclude will always create \r\n * a child scope of the outer scope where the directive is used.\r\n * Which stops us from using ng-repeat type directives where the transcluded \r\n * content accesses something like an item property that is coming\r\n * from the ng-repeat inside the directive template. \r\n * See here for details: https://github.com/angular/angular.js/issues/7874#issuecomment-53450394\r\n * usage:\r\n *\r\n *
\r\n *
\r\n */\r\n@NgComponent({\r\n token: Token.KbTransclude,\r\n dependencies: [\r\n ]\r\n})\r\nexport class KbTransclude extends Directive {\r\n constructor() {\r\n super();\r\n\r\n this.restrict = \"EAC\";\r\n this.link = (scope, element: JQuery, atts, ctrl, $transclude) => {\r\n if (!$transclude) {\r\n throw new Error(\r\n \"Illegal use of ngTransclude directive in the template! \" +\r\n \"No parent directive that requires a transclusion found.\");\r\n }\r\n\r\n let iScopeType = atts.kbTransclude || \"outer\";\r\n var slotName = atts.kbTranscludeSlot; //slot name for multi-slot transclusion\r\n let iChildScope: ng.IScope;\r\n switch (iScopeType) {\r\n // this is the default of angular 1.3+... \r\n // outer is the controller scope where the directive was originally called from\r\n case \"outer\":\r\n $transclude(clone => {\r\n element.empty();\r\n element.append(clone);\r\n }, null, slotName);\r\n break;\r\n case \"parent\": // this will use the scope of the directive\r\n $transclude(scope, clone => {\r\n element.empty();\r\n element.append(clone);\r\n }, null, slotName);\r\n break;\r\n case \"child\": // this will create a new child scope of the directive scope\r\n iChildScope = scope.$new();\r\n $transclude(iChildScope, clone => {\r\n element.empty();\r\n element.append(clone);\r\n element.on(\"$destroy\", () => {\r\n if (iChildScope) {\r\n iChildScope.$destroy();\r\n }\r\n });\r\n }, null, slotName);\r\n break;\r\n }\r\n\r\n scope.$on(\"$destroy\", () => {\r\n if (iChildScope) {\r\n iChildScope.$destroy();\r\n }\r\n });\r\n };\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { ITreeController, ITreeScope } from \"@app/components/kb-tree/kb-tree.component\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { Utils } from \"@tools\";\r\nimport * as angular from \"angular\";\r\n\r\nexport interface ITreeNodeScope extends ng.IScope {\r\n label: string;\r\n /** the name of a template in the template cache that will be used in place of the label */\r\n labelTemplate: string;\r\n /** the name of a template in the template cache that will be used for children */\r\n childTemplate: string;\r\n /** the data item that represents the node */\r\n item: any;\r\n selectable: boolean;\r\n expanded: boolean;\r\n /** the relative path to an image in the media folder */\r\n image: string;\r\n /** the image to show when selected */\r\n imageWhenSelected: string;\r\n /** the name of a kbicon */\r\n icon: string;\r\n /** when skin is \"checks\" on the tree which adds checkboxes, checked controls the value of the checkbox */\r\n checked: boolean;\r\n /** event when a node's checked value has been changed */\r\n checkedChanged: Function;\r\n\r\n valid: boolean;\r\n /** whether this item has children or not. Since children are now 'virtual' \r\n * to increase performance, we need to know \r\n */\r\n hasChildren: boolean;\r\n\r\n // internal \r\n _nodeClick: ($event: ng.IAngularEvent) => void;\r\n _arrowClick: ($event: ng.IAngularEvent) => void;\r\n _parentNode: ITreeNodeScope;\r\n _level: () => number;\r\n _children: ITreeNodeScope[];\r\n _treeScope: ITreeScope;\r\n _icon: string; // calculated icon based on validity\r\n _calculateIcon: () => void;\r\n // _childrenValid: boolean; //whether a direct or indirect child is invalid\r\n // _calculateChildrenValid: () => void;\r\n _getAncestorNodes: (includeThis?: boolean) => ITreeNodeScope[];\r\n _getElement: () => ng.IAugmentedJQuery;\r\n _getHeaderElement: () => ng.IAugmentedJQuery;\r\n _checkedChanged: (item) => void;\r\n}\r\n\r\ninterface ITreeNodeController {\r\n scope: ITreeNodeScope;\r\n\r\n registerNode: (node: ITreeNodeScope) => void;\r\n updateChildTemplate: () => void;\r\n}\r\n\r\n@NgComponent({\r\n token: Token.KbTreeNode,\r\n dependencies: [\r\n Token.$Timeout\r\n ]\r\n})\r\nexport class KbTreeNode extends Directive {\r\n constructor(\r\n $timeout: ng.ITimeoutService\r\n ) {\r\n super();\r\n\r\n this.require = [\"^kbTree\", \"^^?kbTreeNode\", \"kbTreeNode\"];\r\n this.replace = true;\r\n this.template = Dirs.component(\"kb-tree-node\");\r\n this.restrict = \"AE\";\r\n\r\n this.scope = {\r\n label: \"@\",\r\n selectable: \"=?\",\r\n expanded: \"=?\",\r\n item: \"=?\",\r\n image: \"@\",\r\n imageWhenSelected: \"@\",\r\n icon: \"@\",\r\n valid: \"=?\",\r\n checked: \"=?\",\r\n checkedChanged: \"&\",\r\n labelTemplate: \"@\",\r\n childTemplate: \"@\",\r\n hasChildren: \"=?\"\r\n };\r\n this.transclude = true;\r\n\r\n this.controller = [\r\n \"$scope\",\r\n \"$element\",\r\n \"$attrs\",\r\n \"$transclude\",\r\n \"$templateCache\",\r\n Token.$Compile.key,\r\n function(\r\n $scope: ITreeNodeScope,\r\n $element: ng.IAugmentedJQuery,\r\n $attrs: ng.IAttributes,\r\n $transclude: ng.ITranscludeFunction,\r\n $templateCache: ng.ITemplateCacheService,\r\n $compile: ng.ICompileService) {\r\n this.scope = $scope;\r\n let timeouts: ng.IPromise[] = [];\r\n let treeController: ITreeController = $element.controller(\"kbTree\");\r\n // let loadAllNodes = false;\r\n let childTemplateProcessed = false;\r\n // if (treeController) loadAllNodes = treeController.scope.loadAllNodes;\r\n\r\n $scope._children = [];\r\n // $scope._childrenValid = true;\r\n this.registerNode = (node: ITreeNodeScope) => {\r\n $scope._children.push(node);\r\n let off = node.$on(\"$destroy\", event => {\r\n $scope._children.remove(node);\r\n off();\r\n });\r\n };\r\n\r\n // $scope._calculateChildrenValid = () => {\r\n // for (var i = 0; i < $scope._children.length; i++) {\r\n // var node = $scope._children[i];\r\n // if (!node.valid || !node._childrenValid) {\r\n // $scope._childrenValid = false;\r\n // return;\r\n // }\r\n // }\r\n // $scope._childrenValid = true;\r\n // };\r\n $scope._getElement = () => {\r\n return $element;\r\n };\r\n let $headerElem: angular.IAugmentedJQuery;\r\n $scope._getHeaderElement = () => {\r\n if (!$headerElem) $headerElem = $element.find(\">.kb-tree__header\");\r\n return $headerElem;\r\n };\r\n\r\n $scope._calculateIcon = () => {\r\n if (!$scope.valid) {\r\n $scope._icon = \"error\";\r\n // } else if (!$scope._childrenValid) {\r\n // $scope._icon = \"childError\";\r\n } else if ($scope.icon) {\r\n $scope._icon = $scope.icon;\r\n } else {\r\n $scope._icon = null;\r\n }\r\n };\r\n\r\n $scope._getAncestorNodes = (includeThis = true) => {\r\n let ancestorNodes = (includeThis ? [$scope] : []);\r\n let parent = $scope;\r\n do {\r\n parent = parent._parentNode;\r\n if (parent) {\r\n ancestorNodes.push(parent);\r\n }\r\n } while (parent);\r\n\r\n return ancestorNodes;\r\n };\r\n \r\n // if a label template was passed in then get it from the template cache\r\n if ($scope.labelTemplate) {\r\n const templateHtml = $templateCache.get($scope.labelTemplate);\r\n if (!templateHtml) {\r\n throw \"Could not find template for \" + $scope.labelTemplate;\r\n }\r\n let $template = angular.element(templateHtml);\r\n // compile the template\r\n let compiled = $compile($template, $transclude);\r\n // append it to the label\r\n $element.find(\".kb-tree__label\").empty().append($template);\r\n // now link it to the parent scope(we don't want this scope because it's an isolate scope)\r\n compiled($scope.$parent);\r\n }\r\n\r\n let childScope: ng.IScope;\r\n let addChildTemplate = () => {\r\n if (!childTemplateProcessed) {\r\n // if a child template was provided, then use that instead of the transclusion content\r\n if ($scope.childTemplate) {\r\n const templateHtml = $templateCache.get($scope.childTemplate);\r\n if (!templateHtml) {\r\n throw \"Could not find template for \" + $scope.childTemplate;\r\n }\r\n let $template = angular.element(templateHtml);\r\n // compile the template\r\n let compiled = $compile($template, $transclude);\r\n // append it to the label\r\n $element.find(\".kb-tree__node-children\").empty().append($template);\r\n childScope = $scope.$parent.$new();\r\n // now link it to the parent scope(we don't want this scope because it's an isolate scope)\r\n compiled(childScope);\r\n } else { // no child template was provided so use the content of the directive\r\n $transclude((clone, cloneScope) => {\r\n childScope = cloneScope;\r\n $element.find(\".kb-tree__node-children\").empty().append(clone);\r\n });\r\n }\r\n childTemplateProcessed = true;\r\n }\r\n };\r\n\r\n // if (loadAllNodes) {\r\n // addChildTemplate();\r\n // }\r\n\r\n \r\n this.updateChildTemplate = () => {\r\n // if (!loadAllNodes) {\r\n if ($scope.expanded) {\r\n addChildTemplate();\r\n } else {\r\n // timeouts.push($timeout(() => {\r\n // if (childScope) childScope.$destroy();\r\n // $element.find(\".kb-tree__node-children\").empty();\r\n // }, 150));\r\n }\r\n // }\r\n };\r\n\r\n $scope.$on(\"$destroy\", () => {\r\n timeouts.forEach(t => $timeout.cancel(t));\r\n if (childScope) childScope.$destroy();\r\n });\r\n }];\r\n\r\n this.compile = (element, atts: any) => {\r\n if (angular.isUndefined(atts.selectable)) {\r\n atts.selectable = \"true\";\r\n }\r\n if (angular.isUndefined(atts.valid)) {\r\n atts.valid = \"true\";\r\n }\r\n if (angular.isUndefined(atts.childrenValid)) {\r\n atts.childrenValid = \"true\";\r\n }\r\n return this.link;\r\n };\r\n\r\n this.link = (\r\n scope: ITreeNodeScope,\r\n element: ng.IAugmentedJQuery,\r\n atts,\r\n controllers: any[]\r\n ) => {\r\n let timeouts: ng.IPromise[] = [];\r\n let treeController: ITreeController = controllers[0];\r\n let parentController: ITreeNodeController = controllers.length > 1 ? controllers[1] : null;\r\n let thisController: ITreeNodeController = controllers[2];\r\n\r\n // get parent scopes to use for selection and expansion\r\n let treeScope = treeController.scope;\r\n scope._treeScope = treeScope;\r\n // register the node with the parent kbTree\r\n treeController.registerNode(scope);\r\n \r\n if (parentController) {\r\n scope._parentNode = parentController.scope;\r\n parentController.registerNode(scope);\r\n }\r\n\r\n // if no data item was given for the node, then we create one\r\n if (!scope.item) {\r\n scope.item = { id: Utils.shortId() };\r\n }\r\n\r\n let updateExpanded = () => {\r\n if (treeScope.expandable) {\r\n // if (treeScope._selectedNode) {\r\n // var ancestorNodes = treeScope._selectedNode._getAncestorNodes();\r\n\r\n // treeScope._nodes.forEach((node) => {\r\n // if (ancestorNodes.contains(node)) node.expanded = true;\r\n // });\r\n // }\r\n\r\n // if (scope.expanded && scope.selectable) {\r\n // //for accordion functionality, we need to make sure that the node that was expanded and\r\n // //it's direct ancestor nodes are the only ones expanded\r\n // if (treeScope.accordion) {\r\n // var ancestorNodes = scope._getAncestorNodes();\r\n\r\n // treeScope._nodes.forEach((node) => {\r\n // node.expanded = ancestorNodes.contains(node);\r\n // });\r\n // } \r\n // }\r\n } else {\r\n scope.expanded = true;\r\n }\r\n };\r\n\r\n scope.$watch(\"expanded\", (newValue, oldValue) => {\r\n // update the child template when expanded is changed... \r\n // this is what makes kbTree do virtual rendering of nodes to increase performance\r\n thisController.updateChildTemplate();\r\n treeController.refreshSelectionLine();\r\n });\r\n\r\n let select = () => {\r\n // select the item if it's selectable\r\n if (treeScope.selectable && scope.selectable) {\r\n // set the selected item on the tree so it can be bound to by controllers\r\n treeScope._selectedNode = scope;\r\n treeScope.selectedItem = scope.item;\r\n }\r\n };\r\n\r\n scope._arrowClick = $event => {\r\n $event.stopPropagation();\r\n scope.expanded = !scope.expanded;\r\n updateExpanded();\r\n };\r\n\r\n scope._nodeClick = ($event: ng.IAngularEvent) => {\r\n // $event.stopPropagation();\r\n // toggle expanded\r\n if (treeScope.accordion) {\r\n // only collapse when this node is already selected\r\n if (treeScope._selectedNode == scope && scope.expanded) {\r\n scope.expanded = false;\r\n } else {\r\n scope.expanded = true;\r\n }\r\n updateExpanded();\r\n }\r\n\r\n select();\r\n \r\n };\r\n\r\n scope._checkedChanged = (item) => {\r\n $timeout(() => {\r\n scope.checkedChanged({ item });\r\n }, 0); \r\n };\r\n\r\n // calculate the levels which is used for margins\r\n scope._level = () => {\r\n return scope._getAncestorNodes().length - 1;\r\n };\r\n updateExpanded();\r\n\r\n // watch for changes in validity to recalculate the icon\r\n scope.$watch(\"valid\", (newValue, oldValue) => {\r\n if (newValue !== oldValue) {\r\n // if (parentController) parentController.scope._calculateChildrenValid();\r\n scope._calculateIcon();\r\n }\r\n });\r\n // watch for changes to the icon provided by the consumer to recalculate\r\n scope.$watch(\"icon\", (newValue, oldValue) => {\r\n scope._calculateIcon();\r\n });\r\n // scope.$watch(\"_childrenValid\", (newValue, oldValue) => {\r\n // if (newValue !== oldValue) {\r\n // if (parentController) parentController.scope._calculateChildrenValid();\r\n // scope._calculateIcon();\r\n // }\r\n // });\r\n if (treeScope.dragDrop) {\r\n\r\n let el = element[0];\r\n let currentDragTarget;\r\n\r\n let getDropPosition = (e: DragEvent, allow: string) => {\r\n let elementPosition = element.offset();\r\n let elementHeight = element.find(\">.kb-tree__header\").outerHeight(true);\r\n let mouseRelativeToElementY = e.clientY - elementPosition.top;\r\n let dropPosition: string;\r\n if (allow == \"any\") {\r\n if (mouseRelativeToElementY < (elementHeight / 4)) {\r\n dropPosition = \"above\";\r\n } else if (mouseRelativeToElementY > (elementHeight * .75)) {\r\n dropPosition = \"below\";\r\n } else {\r\n dropPosition = \"in\";\r\n }\r\n } else if (allow == \"sibling\") {\r\n if (mouseRelativeToElementY < (elementHeight / 2)) {\r\n dropPosition = \"above\";\r\n } else {\r\n dropPosition = \"below\";\r\n }\r\n } else if (allow == \"child\") {\r\n dropPosition = \"in\";\r\n }\r\n\r\n return dropPosition;\r\n };\r\n el.ondragstart = e => {\r\n\r\n treeScope._dragNode = scope;\r\n e.dataTransfer.effectAllowed = \"move\";\r\n e.dataTransfer.setData(\"text/plain\", \"node\");\r\n e.stopPropagation();\r\n\r\n timeouts.push($timeout(() => {\r\n select();\r\n }));\r\n };\r\n el.ondragover = e => {\r\n let allow: string;\r\n if (treeScope.allowDrop()) {\r\n allow = treeScope.allowDrop()(scope.item, treeScope._dragNode.item);\r\n }\r\n\r\n if (allow === \"any\" || allow === \"child\" || allow == \"sibling\") {\r\n // tell the drag drop system the drop is ok by preventingDefault\r\n e.preventDefault();\r\n } else {\r\n e.dataTransfer.dropEffect = \"none\";\r\n }\r\n\r\n let dropPosition = getDropPosition(e, allow);\r\n\r\n element.toggleClass(\r\n \"kb-tree--dropping-child\",\r\n ((allow == \"child\" || allow == \"any\") && dropPosition == \"in\")\r\n );\r\n element.toggleClass(\r\n \"kb-tree--dropping-sibling-below\",\r\n ((allow == \"sibling\" || allow == \"any\") && dropPosition == \"below\")\r\n );\r\n element.toggleClass(\r\n \"kb-tree--dropping-sibling-above\",\r\n ((allow == \"sibling\" || allow == \"any\") && dropPosition == \"above\")\r\n );\r\n\r\n // e.dataTransfer.setData(\"text\", dropPosition);\r\n e.stopPropagation();\r\n treeController.setCurrentDragTarget(e.currentTarget as HTMLElement);\r\n };\r\n // el.ondragenter = e => {\r\n // console.log({ event: \"dragenter\", el: e.currentTarget });\r\n // };\r\n // el.ondragleave = e => {\r\n // if (e.currentTarget === currentDragTarget) {\r\n // removeDropClasses();\r\n // e.stopPropagation();\r\n // console.log({ event: \"dragleave\", el: e.currentTarget });\r\n // } \r\n // };\r\n el.ondrop = e => {\r\n if (e.preventDefault) e.preventDefault();\r\n if (e.stopPropagation) e.stopPropagation();\r\n treeController.removeDropClasses(element);\r\n\r\n timeouts.push($timeout(() => {\r\n if (treeScope._dragNode) {\r\n let target = scope.item;\r\n let source = treeScope._dragNode.item;\r\n if (target != source) {\r\n let allow = treeScope.allowDrop()(target, source);\r\n let dropPosition = getDropPosition(e, allow);\r\n let targetParent = scope._parentNode ? scope._parentNode.item : undefined;\r\n let sourceParent = treeScope._dragNode._parentNode ?\r\n treeScope._dragNode._parentNode.item\r\n : undefined;\r\n\r\n treeScope.dropped()(target, source, targetParent, sourceParent, dropPosition);\r\n treeScope._dragNode = undefined;\r\n // if we just dropped in this node, then expand it\r\n if (dropPosition == \"in\") {\r\n scope.expanded = true;\r\n updateExpanded();\r\n }\r\n }\r\n }\r\n }));\r\n };\r\n el.ondragend = e => {\r\n timeouts.push($timeout(() => {\r\n treeScope._dragNode = undefined;\r\n treeController.setCurrentDragTarget(null);\r\n }));\r\n };\r\n\r\n scope.$on(\"$destroy\", () => {\r\n el.ondragstart = null;\r\n el.ondragover = null;\r\n el.ondragleave = null;\r\n el.ondrop = null;\r\n el.ondragend = null;\r\n scope._parentNode = null;\r\n treeController = null;\r\n treeScope = null;\r\n timeouts.forEach(t => $timeout.cancel(t));\r\n });\r\n }\r\n };\r\n\r\n }\r\n\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { ITreeNodeScope } from \"@app/components/kb-tree/kb-tree-node.component\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { eScrollMode, Utils } from \"@tools\";\r\nimport * as angular from \"angular\";\r\n\r\nexport interface ITreeScope extends ng.IScope {\r\n /** 2 way binding that holds the currently selected data item of the tree */\r\n selectedItem: any;\r\n /** default is false. Makes it such that only one item can be expanded at a time. Not recommended for d&d */\r\n accordion: boolean;\r\n /** default is true. Set to false to make nodes not selectable */\r\n selectable: boolean;\r\n horizontal: boolean;\r\n /** default is true. Set to false to have all nodes expanded with no ability to collapse */\r\n expandable: boolean;\r\n /** set to the name of an angular animation (ex: 'kb-rise') */\r\n animation: string;\r\n /** 'cards' makes it look like admin tool, 'checks' adds checkboxes */\r\n skin: string;\r\n /** default is false. Set to true to allow d&d. */\r\n dragDrop: boolean;\r\n /** 'material' will have selection line */\r\n selectionStyle: string;\r\n /** a class that will be applied to selected nodes */\r\n selectionClass: string;\r\n /** the color of the selection line if the selection mode is 'line'. Options are: accent, primary, contrast */\r\n selectionLineColor: string;\r\n /** controls the tab width mode when horizontal is true. Options are 'fill', 'auto', and 'custom' */\r\n tabWidth: string;\r\n /** required for d&d. Should return empty string for no drop, \"sibling\", or \"child\", or \"any\" */\r\n allowDrop: () => (target, source) => string;\r\n /** required for d&d. Gives the consumer information about the drop so they can modify the model accordingly */\r\n dropped: () => (target, source, targetParent, sourceParent, dropPosition: string) => void;\r\n /** by default kbTree defers loading of nodes until the parent node is expanded. \r\n * This setting forces it to load all nodes at once \r\n */\r\n // loadAllNodes: boolean;\r\n\r\n // internal scope properties\r\n _selectedNode: ITreeNodeScope;\r\n _nodes: ITreeNodeScope[];\r\n _dragNode: ITreeNodeScope; // internal. The node being dragged\r\n _currentDragTarget: HTMLElement;\r\n}\r\n\r\nexport interface ITreeController {\r\n scope: ITreeScope;\r\n registerNode: (node: ITreeNodeScope) => void;\r\n setCurrentDragTarget: (el: HTMLElement) => void;\r\n removeDropClasses: ($target: angular.IAugmentedJQuery) => void;\r\n refreshSelectionLine: () => void;\r\n}\r\n\r\n/**\r\n * KbTree\r\n *\r\n * kbTree can be used in several different ways. \r\n * If you have a hierarchy of like objects that infinitely nest, you can use it like so:\r\n * \r\n * \r\n * \r\n * \r\n * \r\n * \r\n * \r\n * \r\n * in this case you are providing a child template to the tree-node directive, \r\n * which refers to itself. In this way we achieve\r\n * infinite nesting.\r\n * \r\n * If you do NOT need infinite nesting, then you can just add tree-nodes as content \r\n * of other tree-nodes, while NOT providing\r\n * a child template. Like so:\r\n * \r\n * <\r\n * \r\n * \r\n * \r\n * \r\n * \r\n *\r\n */\r\n\r\n@NgComponent({\r\n token: Token.KbTree,\r\n dependencies: [\r\n ]\r\n})\r\nexport class KbTree extends Directive {\r\n constructor() {\r\n\r\n super();\r\n\r\n this.replace = true;\r\n this.template = Dirs.component(\"kb-tree\");\r\n this.restrict = \"AE\";\r\n this.scope = {\r\n selectedItem: \"=?\",\r\n accordion: \"=?\",\r\n skin: \"@\",\r\n selectable: \"=?\",\r\n expandable: \"=?\",\r\n dragDrop: \"=?\",\r\n allowDrop: \"&?\",\r\n dropped: \"&?\",\r\n animation: \"@\",\r\n // loadAllNodes: \"=?\",\r\n horizontal: \"=?\",\r\n selectionStyle: \"=?\",\r\n selectionClass: \"=?\",\r\n selectionLineColor: \"=?\",\r\n tabWidth: \"=?\"\r\n // control: \"=?\"\r\n };\r\n this.transclude = true;\r\n\r\n // add scope defaults to the compile function\r\n this.compile = (element, atts: any) => {\r\n if (!angular.isDefined(atts.selectable)) atts.selectable = \"true\";\r\n if (!angular.isDefined(atts.expandable)) atts.expandable = \"true\";\r\n if (!angular.isDefined(atts.selectionStyle)) atts.selectionStyle = \"'background'\";\r\n if (!angular.isDefined(atts.selectionLineColor)) atts.selectionLineColor = \"'accent'\";\r\n if (!angular.isDefined(atts.tabWidth)) atts.tabWidth = \"'auto'\";\r\n };\r\n\r\n this.controller = [\r\n \"$scope\",\r\n \"$element\",\r\n \"$attrs\",\r\n \"$transclude\",\r\n function (\r\n $scope: ITreeScope,\r\n $element: ng.IAugmentedJQuery,\r\n $attrs: ng.IAttributes,\r\n $transclude: ng.ITranscludeFunction) {\r\n // set the scope of the tree on it's controller so children can access it\r\n this.scope = $scope;\r\n $scope._nodes = [];\r\n\r\n // $scope.control = $scope.control || {};\r\n // $scope.control.expandToNode = (item) => {\r\n // $scope._nodes.forEach(n => setChildrenValid(n));\r\n // };\r\n\r\n // all child nodes register themselves with the tree to handle selection and accordion functionality\r\n this.registerNode = (node: ITreeNodeScope) => {\r\n $scope._nodes.push(node);\r\n let off = node.$on(\"$destroy\", event => {\r\n $scope._nodes.remove(node);\r\n off();\r\n });\r\n };\r\n\r\n this.setCurrentDragTarget = (el: HTMLElement) => {\r\n if (el !== $scope._currentDragTarget && $scope._currentDragTarget) {\r\n this.removeDropClasses($($scope._currentDragTarget));\r\n console.log({ event: \"currentDragChanged\", el });\r\n }\r\n $scope._currentDragTarget = el;\r\n };\r\n\r\n this.removeDropClasses = ($target: angular.IAugmentedJQuery) => {\r\n $target.removeClass(\"kb-tree--dropping-child\");\r\n $target.removeClass(\"kb-tree--dropping-sibling-below\");\r\n $target.removeClass(\"kb-tree--dropping-sibling-above\");\r\n };\r\n\r\n let updateSelectedNode = () => {\r\n for (let node of $scope._nodes) {\r\n if (node.item === $scope.selectedItem) {\r\n let origSelected = $scope._selectedNode;\r\n $scope._selectedNode = node;\r\n scrollToSelectedNode();\r\n refreshSelectionLine();\r\n // expand all parent nodes when a node is selected\r\n node._getAncestorNodes(false).forEach(n => n.expanded = true);\r\n break;\r\n }\r\n }\r\n };\r\n // if the consumer changes the selected item, we update the selected node\r\n $scope.$watch(\"selectedItem\", () => {\r\n updateSelectedNode();\r\n });\r\n // nodes might be added after the selectedItem is set by the consumer, so\r\n // we need to refind the selected node when the nodes collection changes\r\n $scope.$watchCollection(\"_nodes\", () => {\r\n if (!$scope._selectedNode) {\r\n updateSelectedNode();\r\n }\r\n });\r\n\r\n $scope.$watch(\"expandable\", () => {\r\n if (!$scope.expandable) {\r\n $scope._nodes.forEach(n => expandNodeAndChildren(n));\r\n refreshSelectionLine();\r\n }\r\n });\r\n\r\n $scope.$watch(\"horizontal\", () => {\r\n setTimeout(() => refreshSelectionLine(), 0);\r\n });\r\n\r\n $scope.$watch(\"selectionStyle\", () => {\r\n setTimeout(() => refreshSelectionLine(), 0);\r\n });\r\n\r\n $scope.$watch(\"tabWidth\", () => {\r\n setTimeout(() => refreshSelectionLine(), 0);\r\n });\r\n\r\n let expandNodeAndChildren = (node: ITreeNodeScope) => {\r\n node.expanded = true;\r\n node._children.forEach(child => expandNodeAndChildren(child)); \r\n };\r\n\r\n let scrollToSelectedNode = () => {\r\n setTimeout(() => { //the call to JQuery.position() below causes a forced layout. We defer to next $digest so we're not slowing down the page loading in running configurators\r\n if ($scope._selectedNode) {\r\n let $node = $scope._selectedNode._getHeaderElement();\r\n if ($node && $node.length) {\r\n Utils.scrollIntoView({ elem: $node[0], mode: eScrollMode.nearest, animate: true, horizontal: $scope.horizontal });\r\n }\r\n }\r\n\r\n }, 0);\r\n };\r\n\r\n let $selectionLine: angular.IAugmentedJQuery;\r\n let refreshSelectionLine = this.refreshSelectionLine = () => {\r\n if ($scope._selectedNode && $scope.selectionStyle && $scope.selectionStyle.isEqual(\"line\")) {\r\n if (!$selectionLine || !$selectionLine.length) {\r\n $selectionLine = $('
', {\r\n class: \"kb-tree__selection-line\",\r\n appendTo: $element\r\n });\r\n }\r\n let $node = $scope._selectedNode._getElement();\r\n let nodeEl = $node.find(\".kb-tree__header\").first()[0];\r\n\r\n if ($scope.horizontal) {\r\n $selectionLine.css({ left: nodeEl.offsetLeft, width: nodeEl.offsetWidth, bottom: 0, height: \"2px\", top: \"auto\" });\r\n } else {\r\n $selectionLine.css({ top: nodeEl.offsetTop, height: nodeEl.offsetHeight, left: 0, width: \"2px\", bottom: \"auto\" });\r\n } \r\n } else {\r\n if ($selectionLine) $selectionLine.remove();\r\n $selectionLine = null;\r\n }\r\n };\r\n }];\r\n }\r\n\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\n\r\n@NgComponent({\r\n token: Token.KbUiObject,\r\n})\r\nexport class KbUiObject extends Directive {\r\n constructor() {\r\n super();\r\n\r\n this.replace = true;\r\n this.restrict = \"E\";\r\n this.scope = false;\r\n this.template = Dirs.component(\"kb-ui-object\");\r\n\r\n }\r\n}\r\n","import { IInputScope, KbInput } from \"@app/components/kb-input/kb-input.component\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { StorageService } from \"@app/services/storage.service\";\r\nimport { UploadService } from \"@app/services/upload.service\";\r\nimport { IDialogService } from \"@models\";\r\nimport { Utils } from \"@tools\";\r\n\r\ninterface IUploadEventArgs {\r\n file: File;\r\n}\r\ninterface IUploadScope extends IInputScope {\r\n /** the button text */\r\n label: string;\r\n /** to bind to this include the file parameter: */\r\n upload: (args: IUploadEventArgs) => ng.IPromise;\r\n cleared: () => void;\r\n accept: string;\r\n\r\n\r\n _fileName: () => string;\r\n _btnClick: () => void;\r\n _clear: () => void;\r\n _thumbnailDataUrl: any;\r\n}\r\n\r\n@NgComponent({\r\n token: Token.KbUpload,\r\n dependencies: [\r\n Token.$Timeout,\r\n Token.UploadService,\r\n Token.DialogService,\r\n Token.StorageService\r\n ]\r\n})\r\nexport class KbUpload extends KbInput {\r\n constructor(\r\n $timeout: ng.ITimeoutService,\r\n uploadService: UploadService,\r\n dialogService: IDialogService,\r\n storageService: StorageService\r\n ) {\r\n super($timeout);\r\n\r\n this.restrict = \"EA\";\r\n this.scope = Utils.extend(this.scope, {\r\n upload: \"&\",\r\n cleared: \"&\",\r\n accept: \"@\"\r\n });\r\n this.template = Dirs.component(\"kb-upload\");\r\n\r\n this.link = (scope: IUploadScope, element: ng.IAugmentedJQuery, atts: ng.IAttributes) => {\r\n\r\n scope._fileName = () => {\r\n if (atts.guid && scope.ngModel && scope.ngModel.path) {\r\n return scope.ngModel.path.substr(scope.ngModel.path.indexOf(\"_\") + 1);\r\n } else {\r\n return scope.ngModel.path;\r\n }\r\n };\r\n scope._clear = () => {\r\n dialogService.confirm(\"Are you sure you want to remove this upload?\", () => {\r\n scope.ngModel.path = null;\r\n scope.ngModel.assetId = null;\r\n scope._thumbnailDataUrl = \"\";\r\n scope.ngChange();\r\n scope.cleared();\r\n });\r\n };\r\n scope._btnClick = () => {\r\n uploadService.promptUserToChooseFile(scope.accept).then((file: File) => {\r\n if (!scope.ngModel) scope.ngModel = {path: null, assetId: null};\r\n scope.ngModel.path = file.name;\r\n let uploadPromise = scope.upload({ file }).then(() => {\r\n // only trigger valuechange when upload is done so the rules have\r\n // the file(especially important for images being uploaded to the scene)\r\n scope.ngChange();\r\n });\r\n \r\n // show a thumbnail of the image\r\n if (file.type.match(\"image.*\")) {\r\n scope._thumbnailDataUrl = storageService.getAssetUrl(\"images/spinning_circle.gif\");\r\n let reader = new FileReader();\r\n reader.onloadend = () => {\r\n scope._thumbnailDataUrl = reader.result;\r\n reader.onloadend = null;\r\n };\r\n reader.readAsDataURL(file);\r\n } else {\r\n scope._thumbnailDataUrl = null;\r\n }\r\n });\r\n };\r\n };\r\n }\r\n}\r\n","import { Directive } from \"@app/components/directive\";\r\nimport { NgComponent } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Dirs, eBundle } from \"@app/helpers/dirs\";\r\nimport { eValidationType, IValidationMessage } from \"@models\";\r\n\r\nexport interface IValidationMessagesScope extends ng.IScope {\r\n ngModel: IValidationMessage[];\r\n messageClicked: (msg: IValidationMessage) => void;\r\n hideAutoValidation: boolean;\r\n autoValidation: boolean;\r\n\r\n _toggleAutoValidation: () => void;\r\n _getTitle: () => string;\r\n}\r\n\r\n/**\r\n * For showing validation messages of a configurator\r\n */\r\n@NgComponent({\r\n token: Token.KbValidationMessages\r\n})\r\nexport class KbValidationMessages extends Directive {\r\n constructor() {\r\n super();\r\n\r\n this.restrict = \"EA\";\r\n this.template = Dirs.component(\"kb-validation-messages\", eBundle.app);\r\n this.scope = {\r\n ngModel: \"=?\",\r\n messageClicked: \"&\",\r\n hideAutoValidation: \"=?\",\r\n autoValidation: \"=?\"\r\n };\r\n this.replace = true;\r\n this.link = (scope: IValidationMessagesScope, element, atts) => {\r\n scope._toggleAutoValidation = () => {\r\n scope.autoValidation = !scope.autoValidation;\r\n };\r\n\r\n scope._getTitle = () => {\r\n let title: string = \"\";\r\n if (!scope.ngModel || scope.ngModel.length == 0) {\r\n title = loc.noerrors;\r\n } else {\r\n let errors = scope.ngModel.filter(m => m.messageType == eValidationType.error);\r\n let warnings = scope.ngModel.filter(m => m.messageType == eValidationType.warning);\r\n if (errors.length) {\r\n title += errors.length + \" \" + (errors.length > 1 ? loc.errors : loc.error);\r\n }\r\n if (errors.length && warnings.length) {\r\n title += \" / \";\r\n }\r\n if (warnings.length) {\r\n title += warnings.length + \" \" + (warnings.length > 1 ? loc.warnings : loc.warning);\r\n }\r\n }\r\n return title;\r\n };\r\n };\r\n }\r\n}\r\n","import { NgFilter } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { StorageService } from \"@app/services/storage.service\";\r\n\r\n@NgFilter({\r\n token: Token.AssetFilter,\r\n dependencies: [\r\n Token.StorageService\r\n ]\r\n})\r\nexport class AssetFilter {\r\n constructor(\r\n storageService: StorageService\r\n ) {\r\n return ((relativePath: string) => {\r\n return storageService.getAssetUrl(relativePath)\r\n });\r\n }\r\n}\r\n","import { NgFilter } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\n@NgFilter({\r\n token: Token.BytesFilter,\r\n dependencies: [\r\n ]\r\n})\r\nexport class BytesFilter {\r\n constructor() {\r\n return ((bytes, precision) => {\r\n if (isNaN(parseFloat(bytes)) || !isFinite(bytes)) return \"-\";\r\n if (bytes == 0) return \"0 KB\"; \r\n let units = [\"bytes\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\"];\r\n let n = Math.floor(Math.log(bytes) / Math.log(1024));\r\n if (typeof precision === \"undefined\") precision = (n? 1: 0);\r\n return (bytes / Math.pow(1024, Math.floor(n))).toFixed(precision) + \" \" + units[n];\r\n }) as any;\r\n }\r\n\r\n}\r\n","import { NgFilter } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { KbService } from \"@app/services/kb.service\";\r\nimport * as enums from \"@models\";\r\n\r\nexport interface IEnumFilter {\r\n (enumName: string, localize?: boolean):{ name: string; value: string; }[];\r\n}\r\n\r\n// declare module \"angular\" {\r\n// interface IFilterService {\r\n// (name: \"enum\"): IEnumFilter;\r\n// }\r\n// }\r\n\r\n/**\r\n * takes an enum type name and returns an array of name/value pairs\r\n * that have the localization representing the enum value as the name\r\n * and the value as the string value for the enum\r\n */\r\n@NgFilter({\r\n token: Token.EnumFilter,\r\n dependencies: [\r\n Token.KbService\r\n ]\r\n})\r\nexport class EnumFilter {\r\n constructor(\r\n kbService: KbService\r\n ) {\r\n return ((\r\n enumName: string,\r\n localize = true\r\n ) => {\r\n let enumType = enums[enumName];\r\n let results = [];\r\n for (let i in enumType) {\r\n let locTitle = enumType[i];\r\n let locDesc = null;\r\n if (localize) {\r\n // get the localized value for the enum value. This is convention based\r\n let resxName = enumName + \"_\" + enumType[i] + \"_title\";\r\n locTitle = kbService.loc(resxName);\r\n // if we still have the resx name, then try to see if there is already a matching word\r\n if (locTitle.isEqual(resxName)) {\r\n let low = enumType[i].toLowerCase();\r\n if (loc.hasOwnProperty(low)) {\r\n locTitle = kbService.loc(low);\r\n }\r\n }\r\n\r\n resxName = enumName + \"_\" + enumType[i] + \"_desc\";\r\n locDesc = kbService.loc(resxName);\r\n }\r\n\r\n results.push({ name: locTitle, value: enumType[i], desc: locDesc });\r\n }\r\n return results;\r\n }) as any;\r\n }\r\n}\r\n","import { NgFilter } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { StorageService } from \"@app/services/storage.service\";\r\nimport { IThumbFilter } from \"./thumb.filter\";\r\n\r\nexport interface IFileIconFilter {\r\n (filepath: string, root: string): string;\r\n}\r\n// declare module \"angular\" {\r\n// interface IFilterService {\r\n// (name: \"fileIcon\"): IFileIconFilter;\r\n// }\r\n// }\r\n\r\n@NgFilter({\r\n token: Token.FileIconFilter,\r\n dependencies: [\r\n Token.$Filter,\r\n Token.StorageService\r\n ]\r\n})\r\nexport class FileIconFilter {\r\n constructor(\r\n private $filter: ng.IFilterService,\r\n private storageService: StorageService\r\n ) {\r\n return ((\r\n filepath: string,\r\n root: string = \"media\"\r\n ) => {\r\n let ext = filepath && filepath.substr(filepath.lastIndexOf(\".\"));\r\n if (ext) ext = ext.toLowerCase();\r\n let imageName = \"\";\r\n\r\n switch (ext) {\r\n case \".docx\":\r\n case \".doc\":\r\n imageName = \"docx.png\";\r\n break;\r\n case \".xlsx\":\r\n case \".xls\":\r\n imageName = \"xlsx.png\";\r\n break;\r\n case \".txt\":\r\n imageName = \"txt.png\";\r\n break;\r\n case \".xml\":\r\n imageName = \"xml.png\";\r\n break;\r\n case \".pdf\":\r\n imageName = \"pdf.png\";\r\n break;\r\n case \".sldasm\":\r\n imageName = \"sldasm.png\";\r\n break;\r\n case \".sldprt\":\r\n imageName = \"sldprt.png\";\r\n break;\r\n case \".slddrw\":\r\n imageName = \"slddrw.png\";\r\n break;\r\n case \".iam\":\r\n imageName = \"default.png\";\r\n break;\r\n case \".ipt\":\r\n imageName = \"default.png\";\r\n break;\r\n case \".idw\":\r\n imageName = \"default.png\";\r\n break;\r\n case \".dwg\":\r\n imageName = \"dwg.png\";\r\n break;\r\n case \".dxf\":\r\n imageName = \"dxf.png\";\r\n break;\r\n case \".webm\":\r\n case \".ogv\":\r\n case \".mp4\":\r\n case \".3gp\":\r\n case \".avi\":\r\n imageName = \"video.png\";\r\n break;\r\n case \".png\":\r\n case \".gif\":\r\n case \".jpg\":\r\n case \".bmp\":\r\n if (root == \"media\") {\r\n return (($filter as any)(\"thumb\") as IThumbFilter)(filepath);\r\n } else {\r\n imageName = \"image.png\";\r\n break;\r\n }\r\n case \".zip\":\r\n imageName = \"zip.png\";\r\n break;\r\n default:\r\n imageName = \"default.png\";\r\n break;\r\n }\r\n\r\n return storageService.getAssetUrl(\"images/file_icons/\" + imageName);\r\n\r\n }) as any;\r\n }\r\n\r\n}\r\n","import { NgFilter } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\nexport interface IFileIdFilter {\r\n (fileName: string): string;\r\n}\r\n// declare module \"angular\" {\r\n// interface IFilterService {\r\n// (name: \"fileId\"): IFileIdFilter;\r\n// }\r\n// }\r\n\r\n/**\r\n * Takes file name and strips non alpha-numeric characters out to make it compatible with\r\n * HTML ids, for instance.\r\n */\r\n@NgFilter({\r\n token: Token.FileIdFilter,\r\n dependencies: [\r\n ]\r\n})\r\nexport class FileIdFilter {\r\n constructor() {\r\n return ((fileName: string) => {\r\n return fileName.replace(/[^A-Z0-9]/gi, \"_\");\r\n }) as IFileIdFilter as any;\r\n }\r\n}\r\n","import { NgFilter } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { KbService } from \"@app/services/kb.service\";\r\nimport { IKbCurrencyFilter } from \"./kb-currency.filter\";\r\n\r\n@NgFilter({\r\n token: Token.FxConvertFilter,\r\n dependencies: [\r\n Token.$Filter,\r\n Token.KbService,\r\n ]\r\n})\r\nexport class FxConvertFilter {\r\n constructor(\r\n $filter: ng.IFilterService,\r\n kbService: KbService\r\n ) {\r\n return ((value: number, currencyCode?: string, precision?: number) => {\r\n if (value == null) return \"\";\r\n let formattedValue = value.toString();\r\n if (currencyCode) {\r\n let convertedValue = kbService.fxConvert(value, currencyCode.toUpperCase());\r\n formattedValue = (($filter as any)(\"kbCurrency\") as IKbCurrencyFilter)(convertedValue, currencyCode.toUpperCase(), precision);\r\n }\r\n return formattedValue;\r\n } ) as any;\r\n }\r\n}\r\n","import { NgFilter } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\n@NgFilter({\r\n token: Token.GetFileExtensionFilter,\r\n dependencies: [\r\n ]\r\n})\r\nexport class GetFileExtensionFilter {\r\n constructor() {\r\n return ((path: string) => {\r\n\r\n let filename = path.substring(path.lastIndexOf(\"/\") + 1);\r\n\r\n return filename.substring(path.lastIndexOf(\".\") + 1);\r\n }) as any;\r\n }\r\n\r\n}\r\n","import { NgFilter } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\n@NgFilter({\r\n token: Token.GetFilenameFilter,\r\n dependencies: [\r\n ]\r\n})\r\nexport class GetFilenameFilter {\r\n constructor() {\r\n return ((path: string) => {\r\n\r\n let filename = path.substring(path.lastIndexOf(\"/\") + 1);\r\n\r\n return filename;\r\n }) as any;\r\n }\r\n\r\n}\r\n","import { NgFilter } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { AuthService } from \"@app/services/auth.service\";\r\n\r\n@NgFilter({\r\n token: Token.HasRoleFilter,\r\n dependencies: [\r\n Token.AuthService\r\n ]\r\n})\r\nexport class HasRoleFilter {\r\n constructor(\r\n private authService: AuthService\r\n ) {\r\n return ((role: string) => {\r\n return this.authService.hasRole(role);\r\n }) as any;\r\n }\r\n}\r\n","import { icons } from \"@tools\";\r\nimport { NgFilter } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\n@NgFilter({\r\n token: Token.IconFilter,\r\n dependencies: [\r\n ]\r\n})\r\nexport class IconFilter {\r\n constructor() {\r\n return ((key: string) => {\r\n if (key) key = key.toCamelCase();\r\n let icon = icons[key];\r\n if (!icon) {\r\n icon = key;\r\n }\r\n\r\n return icon;\r\n }) as any;\r\n }\r\n}\r\n","import { NgFilter } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { AuthService } from \"@app/services/auth.service\";\r\nimport { IUser } from \"@models\";\r\n\r\n@NgFilter({\r\n token: Token.IsAdminOrCompanyAdminFilter,\r\n dependencies: [\r\n Token.AuthService\r\n ]\r\n})\r\nexport class IsAdminOrCompanyAdminFilter {\r\n constructor(\r\n private authService: AuthService\r\n ) {\r\n return ((user: IUser) => {\r\n return this.authService.isAdminOrCompanyAdmin();\r\n }) as any;\r\n }\r\n}\r\n","import { NgFilter } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { IRootScope } from \"@models\";\r\nimport { currencies } from \"@tools\";\r\n\r\nexport interface IKbCurrencyFilter {\r\n (value: number, currencyCode?: string, precision?: number): string;\r\n}\r\n// declare module \"angular\" {\r\n// interface IFilterService {\r\n// (name: \"kbCurrency\"): IKbCurrencyFilter;\r\n// }\r\n// }\r\n\r\n@NgFilter({\r\n token: Token.KbCurrencyFilter,\r\n dependencies: [\r\n Token.$Filter,\r\n Token.$RootScope,\r\n Token.$Locale,\r\n ]\r\n})\r\nexport class KbCurrencyFilter {\r\n constructor(\r\n $filter: ng.IFilterService,\r\n $rootScope: IRootScope,\r\n $locale: ng.ILocaleService\r\n ) {\r\n return ((value: number, currencyCode?: string, precision?: number) => {\r\n\r\n // if no iso given, then assume it's the company base currency\r\n // in future, should be the currency of the active quote\r\n if (!currencyCode) {\r\n // if ($rootScope.quote) {\r\n // currencyCode = $rootScope.quote.currency;\r\n // }\r\n // else {\r\n currencyCode = $rootScope.companySettings.currency;\r\n // }\r\n }\r\n\r\n currencyCode = currencyCode.toUpperCase();\r\n\r\n let symbol = currencies[currencyCode] || \"\";\r\n let formatted: string = $filter(\"currency\")(Number(value), undefined, precision);\r\n let localSymbol = $locale.NUMBER_FORMATS.CURRENCY_SYM;\r\n\r\n // replace local symbol in formatted with the real symbol\r\n formatted = formatted.replace(localSymbol, symbol);\r\n\r\n // add the iso code at the end\r\n formatted = formatted + \" \" + currencyCode;\r\n\r\n return formatted;\r\n }) as IKbCurrencyFilter as any;\r\n }\r\n}\r\n","import { NgFilter } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\n@NgFilter({\r\n token: Token.KbDateTimeFilter,\r\n dependencies: [\r\n ]\r\n})\r\nexport class KbDateTimeFilter {\r\n constructor() {\r\n return ((d: Date) => {\r\n return d.getFullYear().toString() + \"/\" +\r\n (d.getMonth() + 1).toString() + \"/\" +\r\n d.getDate().toString() + \" \" +\r\n d.getHours() + \":\" +\r\n d.getMinutes();\r\n }) as any;\r\n }\r\n}\r\n","import { NgFilter } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\n@NgFilter({\r\n token: Token.KbDateFilter,\r\n dependencies: [\r\n ]\r\n})\r\nexport class KbDateFilter {\r\n constructor() {\r\n return ((d: Date) => {\r\n return d.getFullYear().toString() + \"/\" + (d.getMonth() + 1).toString() + \"/\" + d.getDate().toString();\r\n }) as any;\r\n }\r\n}\r\n","import { NgFilter } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\n/**\r\n * converts a number of days to a human readable format: like '10 days', '7.5 weeks', '3 months'\r\n */\r\n\r\n@NgFilter({\r\n token: Token.LeadTimeFilter,\r\n dependencies: [\r\n ]\r\n})\r\nexport class LeadTimeFilter {\r\n constructor() {\r\n return ((days: number, singular: boolean = false) => {\r\n if (days < 14) {\r\n return days + \" \" + (singular ? loc.day : loc.days);\r\n } else if (days < 90) {\r\n return (days / 7).rounder(1).toString() + \" \" + (singular ? loc.week : loc.weeks);\r\n } else {\r\n return (days / 30.42).rounder(1).toString() + \" \" + (singular ? loc.month : loc.months);\r\n }\r\n }) as any;\r\n }\r\n}\r\n","import { NgFilter } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\n@NgFilter({\r\n token: Token.LocFilter,\r\n dependencies: [\r\n ]\r\n})\r\nexport class LocFilter {\r\n constructor() {\r\n return ((key: string, ...replacements: string[]) => {\r\n if (key) {\r\n // replacements = [replacement1, replacement2];\r\n let lkey = key.toLowerCase();\r\n let localizedString = loc[lkey];\r\n if (localizedString) {\r\n let result = localizedString.format.apply(localizedString, replacements);\r\n return result;\r\n }\r\n }\r\n return key;\r\n }) as any;\r\n }\r\n}\r\n","import { eLogType } from \"@models\";\r\nimport { icons } from \"@tools\";\r\nimport { NgFilter } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\n@NgFilter({\r\n token: Token.LogIconFilter,\r\n dependencies: [\r\n ]\r\n})\r\nexport class LogIconFilter {\r\n constructor() {\r\n return ((type: string) => {\r\n switch (type) {\r\n case eLogType.error:\r\n return icons.error;\r\n case eLogType.info:\r\n return icons.info;\r\n default:\r\n return icons.success;\r\n }\r\n }) as any;\r\n }\r\n}\r\n","import { NgFilter } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { StorageService } from \"@app/services/storage.service\";\r\n\r\nexport interface IMediaFilter {\r\n (mediaPath: string): string;\r\n}\r\n// declare module \"angular\" {\r\n// interface IFilterService {\r\n// (name: \"media\"): IMediaFilter;\r\n// }\r\n// }\r\n\r\n@NgFilter({\r\n token: Token.MediaFilter,\r\n dependencies: [\r\n Token.StorageService\r\n ]\r\n})\r\nexport class MediaFilter {\r\n constructor(\r\n storageService: StorageService\r\n ) {\r\n return ((mediaPath: string) => {\r\n if (!mediaPath) {\r\n return storageService.getFallbackImage();\r\n } else {\r\n return storageService.getMediaUrl(mediaPath);\r\n }\r\n }) as IMediaFilter as any;\r\n }\r\n\r\n}\r\n","import { eNotificationType } from \"@models\";\r\nimport { icons } from \"@tools\";\r\nimport { NgFilter } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\n@NgFilter({\r\n token: Token.NotificationIconFilter,\r\n dependencies: [\r\n ]\r\n})\r\nexport class NotificationIconFilter {\r\n constructor() {\r\n return ((type: string) => {\r\n switch (type) {\r\n case eNotificationType.quoteApproved:\r\n return icons.approve;\r\n case eNotificationType.quoteRejected:\r\n return icons.reject;\r\n default:\r\n return icons.user;\r\n }\r\n }) as any;\r\n }\r\n}\r\n","import { NgFilter } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\n@NgFilter({\r\n token: Token.NumberFormateFilter,\r\n dependencies: [\r\n ]\r\n})\r\nexport class NumberFormatFilter {\r\n constructor() {\r\n return ((\r\n value: number,\r\n format?: string,\r\n minPrecision?: number,\r\n maxPrecision?: number,\r\n currency?: string,\r\n decimalSeparator?: string,\r\n thousandsSeparator?: string,\r\n prefix?: string,\r\n suffix?: string) => {\r\n return value.format({\r\n formatType: format,\r\n minPrecision: Number(minPrecision),\r\n maxPrecision: Number(maxPrecision),\r\n currency,\r\n decimalSeparator,\r\n thousandsSeparator,\r\n prefix,\r\n suffix\r\n });\r\n } ) as any;\r\n }\r\n}\r\n","import { NgFilter } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { StorageService } from \"@app/services/storage.service\";\r\n\r\nexport interface IProfileImageFilter {\r\n (path: string): string;\r\n}\r\n\r\n@NgFilter({\r\n token: Token.ProfileImageFilter,\r\n dependencies: [\r\n Token.StorageService\r\n ]\r\n})\r\nexport class ProfileImageFilter {\r\n constructor(\r\n storageService: StorageService\r\n ) {\r\n return ((path: string) => {\r\n if (!path) {\r\n return storageService.getFallbackImage();\r\n } else {\r\n return storageService.getProfileImageUrl(path);\r\n }\r\n }) as IProfileImageFilter as any;\r\n }\r\n\r\n}\r\n","import { NgFilter } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { StorageService } from \"@app/services/storage.service\";\r\n\r\n@NgFilter({\r\n token: Token.QuoteProductImageFilter,\r\n dependencies: [\r\n Token.StorageService\r\n ]\r\n})\r\nexport class QuoteProductImageFilter {\r\n constructor(\r\n storageService: StorageService\r\n ) {\r\n return ((relativePath: string) => {\r\n if (!relativePath) {\r\n return storageService.getFallbackImage();\r\n } else if (relativePath.startsWith(\"media/\") || relativePath.startsWith(\"productimages/\")) {\r\n // if it's a media file, go straight to the blob storage to spare the round trip and redirect\r\n return storageService.getFileUrl(relativePath);\r\n } else {\r\n return \"/api/\" + relativePath;\r\n }\r\n }) as any;\r\n }\r\n\r\n}\r\n","import { NgFilter } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\n/**\r\n * used in ng-repeat to have something like a for loop instead of looping over a collection\r\n */\r\n@NgFilter({\r\n token: Token.RangeFilter,\r\n dependencies: [\r\n ]\r\n})\r\nexport class RangeFilter {\r\n constructor() {\r\n return ((input: any[], total: number) => {\r\n\r\n total = parseInt(total as any, 10);\r\n for (let i = 0; i < total; i++) {\r\n input.push(i);\r\n }\r\n\r\n return input;\r\n }) as any;\r\n }\r\n}\r\n","import { NgFilter } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\n/**\r\n * convert html to raw text\r\n */\r\n@NgFilter({\r\n token: Token.RawTextFilter,\r\n dependencies: [\r\n ]\r\n})\r\nexport class RawTextFilter {\r\n constructor() {\r\n return ((html: string) => {\r\n return String(html).replace(/<(?:.|\\n)*?>/gm, \"\");\r\n }) as any;\r\n }\r\n\r\n}\r\n","import { NgFilter } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\n@NgFilter({\r\n token: Token.ShadeFilter,\r\n dependencies: [\r\n ]\r\n})\r\nexport class ShadeFilter {\r\n constructor() {\r\n return ((shadeEnumValue: string, colorName: string) => {\r\n let shadeNum: number = 50;\r\n if (shadeEnumValue.startsWith(\"lighter\")) {\r\n shadeNum = Number(shadeEnumValue.substr(7)) * 10;\r\n } else if (shadeEnumValue.startsWith(\"darker\")) {\r\n shadeNum = (Number(shadeEnumValue.substr(6)) * 10) + 50;\r\n }\r\n let prefix = \"kb-background\";\r\n return `${prefix}--${colorName.toLowerCase()}-${shadeNum}`;\r\n }) as any;\r\n }\r\n}\r\n","import { NgFilter } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { Color } from \"@tools\";\r\n\r\n/**\r\n * Given a background color, will provide a contrasting foreground color as a hex code\r\n */\r\n@NgFilter({\r\n token: Token.SmartColorFilter,\r\n dependencies: [\r\n ]\r\n})\r\nexport class SmartColorFilter {\r\n constructor() {\r\n return ((backgroundHex: string) => {\r\n let color: Color;\r\n let background: Color = new Color(backgroundHex);\r\n if (background.isDark()) {\r\n color = new Color({ r: 250, g: 250, b: 250 });\r\n } else {\r\n color = new Color({ r: 17, g: 17, b: 17 });\r\n }\r\n return color.toHexString();\r\n }) as any;\r\n }\r\n}\r\n","import { NgFilter } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { ThemeService } from \"@app/services/theme.service\";\r\nimport { IRootScope } from \"@models\";\r\n\r\n@NgFilter({\r\n token: Token.ThemeColorFilter,\r\n dependencies: [\r\n Token.ThemeService,\r\n Token.$RootScope\r\n ]\r\n})\r\nexport class ThemeColorFilter {\r\n constructor(themeService: ThemeService, $rootScope: IRootScope) {\r\n return ((palette: string, shadeEnumValue: string, opacity: number, contrast: boolean) => {\r\n let shadeNum: number = 50;\r\n if (shadeEnumValue.startsWith(\"lighter\")) {\r\n shadeNum = Number(shadeEnumValue.substr(7)) * 10;\r\n } else if (shadeEnumValue.startsWith(\"darker\")) {\r\n shadeNum = (Number(shadeEnumValue.substr(6)) * 10) + 50;\r\n }\r\n\r\n if (palette == \"warning\") {\r\n palette = \"warn\";\r\n }\r\n return themeService.getRgbString(themeService.getActiveTheme(), palette, shadeNum, opacity, contrast, false);\r\n }) as any;\r\n }\r\n}\r\n","import { NgFilter } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { StorageService } from \"@app/services/storage.service\";\r\nimport { Utils } from \"@tools\";\r\n\r\nexport interface IThumbFilter {\r\n (mediaPath: string, width?: number, height?: number): string;\r\n}\r\n// declare module \"angular\" {\r\n// interface IFilterService {\r\n// (name: \"thumb\"): IThumbFilter;\r\n// }\r\n// }\r\n\r\n@NgFilter({\r\n token: Token.ThumbFilter,\r\n dependencies: [\r\n Token.StorageService\r\n ]\r\n})\r\nexport class ThumbFilter {\r\n constructor(storageService: StorageService) {\r\n return ((mediaPath: string, width?: number, height?: number) => {\r\n let path = mediaPath;\r\n\r\n if (mediaPath) {\r\n if (!Utils.isAbsoluteUrl(mediaPath)) {\r\n // if the consumer is asking for a size bigger than our thumbnails, then we load the full res image\r\n if ((width && width > 90) || (height && height > 90)) {\r\n path = storageService.getMediaUrl(mediaPath);\r\n } else { // size is thumbnail size or lower, so we load the thumbnail for speed\r\n path = `${storageService.getMediaUrl(mediaPath)}?width=96&height=96`;\r\n }\r\n }\r\n }\r\n \r\n return path;\r\n }) as IThumbFilter as any;\r\n }\r\n\r\n}\r\n","import * as angular from \"angular\";\r\nimport { NgFilter } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\n@NgFilter({\r\n token: Token.TruncateFilter,\r\n dependencies: [\r\n ]\r\n})\r\nexport class TruncateFilter {\r\n constructor() {\r\n return ((text: string, length: number, end: string) => {\r\n if (isNaN(length)) {\r\n length = 10;\r\n }\r\n \r\n if (!angular.isDefined(end)) {\r\n end = \"...\";\r\n }\r\n\r\n if (!text || text.length - end.length <= length) {\r\n return text;\r\n } else {\r\n return String(text).substring(0, length - end.length) + end;\r\n }\r\n }) as any;\r\n }\r\n\r\n}\r\n","import { NgFilter } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\n@NgFilter({\r\n token: Token.TrustAsHtmlFilter,\r\n dependencies: [\r\n Token.$Sce\r\n ]\r\n})\r\nexport class TrustAsHtmlFilter {\r\n constructor($sce: ng.ISCEService) {\r\n return (html => {\r\n return $sce.trustAsHtml(html);\r\n }) as any;\r\n }\r\n}\r\n","import { BaseController, IBaseScope } from \"@app/views/base.view\";\r\nimport { CrudController } from \"@app/views/crud.view\";\r\nimport { events, Utils } from \"@tools\";\r\nimport { NgView } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { IKbUserRegister, eEnvironment } from \"@models\";\r\nimport { AuthService } from \"@app/services/auth.service\";\r\nimport { IRootScope } from \"@models\";\r\n\r\nexport interface ILogin {\r\n email?: string;\r\n password?: string;\r\n rememberMe?: boolean;\r\n}\r\n\r\nexport interface IForgotPassword {\r\n email?: string;\r\n}\r\n\r\nexport enum eLoginMode {\r\n login,\r\n register,\r\n thanks,\r\n forgotPassword,\r\n forgotPasswordSubmitted\r\n}\r\n\r\nexport interface ILoginScope extends IBaseScope {\r\n loginModel: ILogin;\r\n userModel: IKbUserRegister;\r\n forgotPasswordModel: IForgotPassword;\r\n registrationModel: any;\r\n validation: any;\r\n ssoEnabled: boolean;\r\n ssoSignIn: () => void;\r\n showAltLogin: () => void;\r\n\r\n login: () => void;\r\n loginVisible: boolean;\r\n loginError: string;\r\n altLogin: boolean;\r\n\r\n submitForgotPassword: () => ng.IPromise;\r\n\r\n mode: eLoginMode;\r\n setMode: (mode: eLoginMode) => void;\r\n register: () => ng.IPromise;\r\n}\r\n\r\n@NgView({\r\n token: Token.LoginView,\r\n dependencies: [\r\n Token.$Scope,\r\n Token.$Http,\r\n Token.AuthService,\r\n Token.$RootScope,\r\n Token.$Timeout,\r\n Token.$Window,\r\n Token.$Location\r\n ]\r\n})\r\nexport class LoginController extends BaseController {\r\n constructor(\r\n private $scope: ILoginScope,\r\n private $http: ng.IHttpService,\r\n private authService: AuthService,\r\n private $rootScope: IRootScope,\r\n private $timeout: ng.ITimeoutService,\r\n private $window: ng.IWindowService,\r\n private $location: ng.ILocationService\r\n ) {\r\n\r\n super();\r\n $scope.mode = eLoginMode.login;\r\n $scope.loginModel = {};\r\n $scope.userModel = {};\r\n $scope.forgotPasswordModel = {};\r\n $scope.registrationModel = {};\r\n $scope.ssoEnabled = $rootScope.context.ssoEnabled;\r\n\r\n $scope.login = () => {\r\n authService.login(\r\n $scope.loginModel.email,\r\n $scope.loginModel.password,\r\n $scope.loginModel.rememberMe\r\n ).finally(() => {\r\n $scope.loginError = authService.loginError;\r\n });\r\n };\r\n $scope.loginVisible = false;\r\n\r\n $scope.setMode = mode => {\r\n $scope.mode = mode;\r\n };\r\n\r\n $scope.ssoSignIn = () => {\r\n if (Utils.isDefined($location.search().embedded)) {\r\n Utils.sendMessageToParent({\r\n name: \"loginsso\",\r\n data: {}\r\n });\r\n }\r\n else {\r\n $window.location.href = \"/ssosignin?RedirectUrl=\" + $window.location.href;\r\n }\r\n }\r\n\r\n $scope.showAltLogin = () => {\r\n $scope.altLogin = true;\r\n }\r\n\r\n let off1 = $rootScope.$on(events.loginRequested, () => {\r\n if ($scope.ssoEnabled && Utils.getParameterByName($window.location.href, \"autoSsoLogin\")) {\r\n $scope.ssoSignIn();\r\n }\r\n $scope.loginVisible = true;\r\n });\r\n\r\n let off2 = $rootScope.$on(events.loginSuccessful, () => {\r\n this.$timeout(() => {\r\n // delay emptying while the fade out animation runs\r\n $scope.loginVisible = false;\r\n $scope.loginModel.email = \"\";\r\n $scope.loginModel.password = \"\";\r\n }, 500);\r\n });\r\n\r\n $scope.register = () => {\r\n if (!$scope.registrationModel.agreedToPrivacyPolicy) {\r\n $scope.validation = { agreedToPrivacyPolicy: \"You must agree to the privacy policy before continuing\" };\r\n return;\r\n }\r\n return $http.post(\"/api/auth/register\", $scope.userModel, { tracker: $rootScope.loginTracker }).then(() => {\r\n $scope.mode = eLoginMode.thanks;\r\n }, (r: ng.IHttpResponse) => {\r\n $scope.validation = CrudController.prototype.getValidationObject(r.data, r.status);\r\n });\r\n };\r\n\r\n $scope.submitForgotPassword = () => {\r\n return $http.post(\r\n \"/api/auth/forgotpassword\",\r\n $scope.forgotPasswordModel,\r\n { tracker: $rootScope.loginTracker }\r\n ).then(() => {\r\n $scope.mode = eLoginMode.forgotPasswordSubmitted;\r\n }, (r: ng.IHttpResponse) => {\r\n $scope.validation = CrudController.prototype.getValidationObject(r.data, r.status);\r\n });\r\n };\r\n\r\n if (!$rootScope.context.user && (!$rootScope.context.allowAnonymousLogins || $rootScope.environment !== eEnvironment.prod) && Utils.getParameterByName($window.location.href, \"autoSsoLogin\")) {\r\n $scope.ssoSignIn();\r\n }\r\n\r\n $scope.$on(\"$destroy\", () => {\r\n off1();\r\n off2();\r\n });\r\n }\r\n}\r\n","import { DialogService } from '@app/services/dialog.service';\r\nimport { RuleService } from '@app/services/rule.service';\r\nimport * as kb3d from '@kb3d';\r\nimport {\r\n Configurator,\r\n eEnvironment,\r\n eHotspotAttach,\r\n eHotspotPosition,\r\n Field,\r\n Hotspot,\r\n IConfiguratorRuleArgs,\r\n IConfiguratorSession,\r\n IJsResult,\r\n IScene,\r\n ISceneLoadedData,\r\n ISceneRuleArgs,\r\n ITableObject,\r\n KbObjectManager,\r\n UiObject,\r\n} from '@models';\r\nimport { IMessage, Utils } from '@tools';\r\n\r\n/**\r\n * scope for the dynamically added annotation html layer\r\n */\r\nexport interface ISceneViewerScope {\r\n // extends ng.IScope {\r\n $digest: () => void;\r\n $apply: (fn: () => void) => void;\r\n hotspotClick?: ($event: ng.IAngularEvent, h: Hotspot) => void;\r\n hotspotCloseClick?: ($event: ng.IAngularEvent, h: Hotspot) => void;\r\n loaded?: boolean; //used to start the 'move me' animation\r\n arActive?: () => boolean;\r\n toggleAr?: () => void;\r\n supportsVr?: boolean;\r\n arEnabled?: boolean;\r\n fullscreenEnabled?: boolean;\r\n arLoading?: ng.IPromiseTracker;\r\n allHotspots?: Hotspot[]; //all of the hotspots to process (includes those from nested scenes)\r\n}\r\n\r\nexport interface ILoadSceneArgs {\r\n isStandalone: boolean;\r\n scene: IScene;\r\n clearMemory: boolean;\r\n config: Configurator;\r\n isRenderContext: boolean;\r\n loadingExperience?: boolean;\r\n}\r\n\r\n/**\r\n * The constructor args of sceneViewer are designed such that they are not dependent on angular...\r\n * this is so it can be used on server-side renders without loading the whole UI framework.\r\n */\r\nexport interface ISceneViewerArgs {\r\n environment: eEnvironment;\r\n baseUrl: string;\r\n $q: ng.IQService;\r\n $timeout: (fn: (...args: any[]) => T | ng.IPromise, delay?: number) => void;\r\n //$injector: ng.auto.IInjectorService;\r\n ruleService: RuleService;\r\n dialogService: DialogService;\r\n //$compile: ng.ICompileService;\r\n compileTemplate: (hotspotElem: Element, scope: ISceneViewerScope) => HTMLElement | undefined;\r\n $scope: ISceneViewerScope;\r\n handleRuleError: (ruleName: string, result: IJsResult) => void;\r\n tableArraysDb: { [id: number]: ITableObject };\r\n //helper: ConfiguratorHelper;\r\n /** a promise telling the scene when the configurator has fully loaded */\r\n configuratorLoadedPromise: ng.IPromise;\r\n /**\r\n * the css style selector for the element the viewer should be placed in\r\n */\r\n elemSelector: string;\r\n /**\r\n * if this is an embed, the request id holds an id from the parent page to identify\r\n * which embed is calling back (if they have multiple embeds on the same page)\r\n */\r\n requestId: string;\r\n /**\r\n * a callback for whenever a custom message has been sent by the scene\r\n */\r\n messageCallback: (msg: IMessage) => void;\r\n /**\r\n * a dictionary holding scene definitions for types of scenes that could be instantiated.\r\n * Needed for creating nested scenes\r\n */\r\n sceneDb: { [idScene: number]: IScene };\r\n /**\r\n * a delegate to call when selectPage has been called from the rules (configuratorController should handle this)\r\n */\r\n navigateToElement: (elem: UiObject) => void;\r\n\r\n configSession: IConfiguratorSession;\r\n\r\n arLoading: ng.IPromiseTracker;\r\n highlightColor: string;\r\n clientLanguage: string;\r\n isMobile: boolean;\r\n isRender: boolean;\r\n renderPass: string;\r\n assetRoot: string;\r\n clusterEnv: string;\r\n cacheBuster: string;\r\n lastDeploy: number;\r\n enableScreenshots?: boolean;\r\n}\r\n\r\nexport abstract class SceneViewer {\r\n constructor(private args: ISceneViewerArgs) {\r\n Object.keys(args).forEach(prop => {\r\n this[prop] = args[prop];\r\n });\r\n this.loadDeferred = this.$q.defer();\r\n }\r\n\r\n scene: IScene;\r\n sceneConfig: Configurator;\r\n /**\r\n * if the scene is attached to a full cpq configurator, this will be the cpq configurator,\r\n * otherwise, it will also be the scene configurator\r\n */\r\n uiConfig: Configurator;\r\n $scope: ISceneViewerScope;\r\n protected elem: HTMLElement;\r\n protected hotspotDiv: HTMLElement;\r\n protected loadDeferred: ng.IDeferred;\r\n\r\n //constructor args-------------\r\n environment: eEnvironment;\r\n baseUrl: string;\r\n assetRoot: string;\r\n clusterEnv: string;\r\n cacheBuster: string;\r\n $q: ng.IQService;\r\n $timeout: ng.ITimeoutService;\r\n //$injector: ng.auto.IInjectorService;\r\n ruleService: RuleService;\r\n //$compile: ng.ICompileService;\r\n compileTemplate: (hotspotElem: Element, scope: ISceneViewerScope) => HTMLElement | undefined;\r\n handleRuleError: (ruleName: string, result: IJsResult) => void;\r\n tableArraysDb: { [id: number]: ITableObject };\r\n elemSelector: string;\r\n requestId: string;\r\n messageCallback: (msg: IMessage) => void;\r\n sceneDb: { [idScene: number]: IScene };\r\n navigateToElement: (elem: UiObject) => void;\r\n configSession: IConfiguratorSession;\r\n arLoading: ng.IPromiseTracker;\r\n highlightColor: string;\r\n clientLanguage: string;\r\n isMobile: boolean;\r\n isRender: boolean;\r\n renderPass: string;\r\n configuratorLoadedPromise: ng.IPromise;\r\n //end constructor args---------\r\n\r\n abstract init(): ng.IPromise;\r\n abstract loadSceneInternal(args: ILoadSceneArgs): ng.IPromise;\r\n abstract runRules(waitForLoad: boolean): ng.IPromise;\r\n abstract clearHandlers();\r\n abstract runAction(actionName: string): ng.IPromise>;\r\n abstract runFieldAction(elem: UiObject): ng.IPromise>;\r\n abstract importUploadFieldImage(uiConfig: Configurator, field: Field, file?: File): ng.IPromise;\r\n abstract resize();\r\n abstract snapshot(options: kb3d.ISnapshotArgs | clara2.ISnapshotOptions): Promise;\r\n abstract dispose();\r\n\r\n public loadScene(args: ILoadSceneArgs): ng.IPromise {\r\n // flush out stuff that needs to be flushed\r\n this.clearHandlers();\r\n this.$scope.loaded = false;\r\n this.loadDeferred = this.$q.defer();\r\n\r\n // reset scope\r\n this.scene = args.scene;\r\n if (args.isStandalone) {\r\n //it's a standalone scene, so the uiConfig and sceneConfig are one and the same\r\n this.sceneConfig = args.config;\r\n this.uiConfig = args.config;\r\n this.sceneConfig.$uiConfigurator = args.config;\r\n } else {\r\n //it's a full cpq config, so we make another configurator just for the scene\r\n this.sceneConfig = new Configurator(new KbObjectManager(), this.scene.configurator);\r\n this.sceneConfig.$running = true;\r\n this.sceneConfig.name = this.scene.name;\r\n this.sceneConfig.idScene = this.scene.id;\r\n this.sceneConfig.$uiConfigurator = args.config;\r\n\r\n this.uiConfig = args.config;\r\n this.uiConfig.$sceneConfigurator = this.sceneConfig; //set the sceneConfigurator in the uiconfig so templates have access to it\r\n }\r\n\r\n return this.loadSceneInternal(args);\r\n }\r\n\r\n protected createElem() {\r\n let parentElem = document.querySelector(this.elemSelector) as HTMLElement;\r\n this.elem = document.createElement('div') as HTMLElement;\r\n this.elem.classList.add('kb-viewer__3d');\r\n parentElem.appendChild(this.elem);\r\n }\r\n\r\n protected createHotspotElem() {\r\n // load the hotspot div after the player so it ends up later in the html\r\n this.hotspotDiv = document.createElement('div') as HTMLElement;\r\n this.hotspotDiv.classList.add('kb-viewer__hotspots', 'xr-overlay');\r\n this.hotspotDiv.setAttribute('ng-include', \"'hotspots-template'\");\r\n this.hotspotDiv.setAttribute('ng-if', 'loaded');\r\n this.hotspotDiv.setAttribute('ng-cloak', '');\r\n this.elem.appendChild(this.hotspotDiv);\r\n this.hotspotDiv = this.compileTemplate(this.hotspotDiv, this.$scope);\r\n }\r\n\r\n public show() {\r\n if (this.elem.classList.contains('kb-hide')) {\r\n this.elem.classList.remove('kb-hide');\r\n\r\n // redraw otherwise it won't actually show\r\n this.resize();\r\n }\r\n }\r\n\r\n public hide() {\r\n if (!this.elem.classList.contains('kb-hide')) {\r\n this.elem.classList.add('kb-hide');\r\n }\r\n }\r\n\r\n protected notifyLoaded() {\r\n /* notify any outside pages that are embedding that the scene is loaded. \r\n We pass the requestid that was passed in as a query string param back to \r\n them so they know which iframe has been loaded (in case they have multiple \r\n kbmax iframes on the same page) */\r\n Utils.sendMessageToParent({\r\n name: 'sceneloaded',\r\n data: {\r\n requestId: this.requestId,\r\n } as ISceneLoadedData,\r\n });\r\n Utils.sendMessageToParent({ name: 'progress', data: 0.2 });\r\n\r\n this.$scope.loaded = true;\r\n this.loadDeferred.resolve();\r\n }\r\n\r\n protected runActionRule(actionName: string, ruleArgs: ISceneRuleArgs): ng.IPromise> {\r\n let action = this.sceneConfig.actions.find(a => a.name.isEqual(actionName));\r\n if (action) {\r\n return this.loadDeferred.promise.then(() => {\r\n return this.ruleService.runRuleContainerAsync(action, ruleArgs).then(r => {\r\n this.handleRuleError(action.name + ' ' + action.$type, r);\r\n return r;\r\n });\r\n });\r\n }\r\n }\r\n\r\n protected setFieldsIfStandalone() {\r\n // if this is a standalone scene being used with a full CPQ configurator,\r\n // then we need to set the fields of the scene configurator\r\n if (this.sceneConfig != this.uiConfig && !this.sceneConfig.idProduct) {\r\n this.sceneConfig.setFields(this.uiConfig.getFieldsObject());\r\n }\r\n }\r\n\r\n public sendMessage(msg: IMessage) {\r\n if (this.messageCallback) {\r\n this.messageCallback(msg);\r\n }\r\n // send message to embed consumer\r\n Utils.sendMessageToParent(msg);\r\n }\r\n\r\n public refreshElementParent() {\r\n //get the first visible viewer element\r\n let $parent = $(this.elemSelector + ':visible:first');\r\n\r\n if ($parent.length && this.elem && !$parent.find(this.elem).length) {\r\n $parent[0].appendChild(this.elem);\r\n }\r\n }\r\n\r\n protected positionHotspot(pos: kb3d.IScreenBoundingBox, hotspot: Hotspot) {\r\n hotspot.$top = pos.y;\r\n hotspot.$left = pos.x;\r\n\r\n if (hotspot.popupPosition == eHotspotPosition.target) {\r\n let x = pos.x;\r\n let y = pos.y;\r\n\r\n if (hotspot.popupAttach == eHotspotAttach.top) {\r\n y = pos.top;\r\n } else if (hotspot.popupAttach == eHotspotAttach.bottom) {\r\n y = pos.top + pos.height;\r\n } else if (hotspot.popupAttach == eHotspotAttach.left) {\r\n x = pos.left;\r\n } else if (hotspot.popupAttach == eHotspotAttach.right) {\r\n x = pos.left + pos.width;\r\n } else if (hotspot.popupAttach == eHotspotAttach.topLeft) {\r\n y = pos.top;\r\n x = pos.left;\r\n } else if (hotspot.popupAttach == eHotspotAttach.topRight) {\r\n y = pos.top;\r\n x = pos.left + pos.width;\r\n } else if (hotspot.popupAttach == eHotspotAttach.bottomLeft) {\r\n y = pos.top + pos.height;\r\n x = pos.left;\r\n } else if (hotspot.popupAttach == eHotspotAttach.bottomRight) {\r\n y = pos.top + pos.height;\r\n x = pos.left + pos.width;\r\n }\r\n\r\n x += hotspot.popupOffsetX;\r\n y += hotspot.popupOffsetY;\r\n\r\n if (hotspot.keepPopupInViewer && hotspot.open) {\r\n let $popup = $('#kb-hotspot__popup-' + hotspot.id);\r\n let popupHeight = $popup.height();\r\n let popupWidth = $popup.width();\r\n\r\n if (y < 0) y = 0;\r\n if (y + popupHeight > this.hotspotDiv.clientHeight) {\r\n y = Math.round(this.hotspotDiv.clientHeight - popupHeight);\r\n }\r\n if (x < 0) x = 0;\r\n if (x + popupWidth > this.hotspotDiv.clientWidth) {\r\n x = Math.round(this.hotspotDiv.clientWidth - popupWidth);\r\n }\r\n }\r\n\r\n hotspot.popupTop = y.toString() + 'px';\r\n hotspot.popupLeft = x.toString() + 'px';\r\n hotspot.popupRight = 'auto';\r\n hotspot.popupBottom = 'auto';\r\n }\r\n }\r\n\r\n protected getAllHotspots(): Hotspot[] {\r\n let allHotspots = [];\r\n let allUiConfigs = [this.uiConfig].concat(this.uiConfig.getAllConfigurators());\r\n for (let uic of allUiConfigs) {\r\n if (uic.$sceneConfigurator && (uic == this.uiConfig || uic.$nestHotspots))\r\n allHotspots.pushArray(uic.$sceneConfigurator.hotspots);\r\n }\r\n return allHotspots;\r\n }\r\n}\r\n","import { ClaraSceneService, ClaraSceneUtilities, eHighlightType, SceneCache } from \"@app/helpers/clara-scene.service\";\r\nimport { Configurator, eDragMode, eHotspotShape, eRuleType, Field, Hotspot, IAddModelClickHandlerArgs, IClaraSceneRuleArgs, IClickArgs, IConstrainCameraArgs, IDietCompany, IDragArgs, IDraggable, IGetTableRuleArgs, IGetUploadImageNodeArgs, IHandler, IHandlerDb, IJsResult, ISceneAnimationArgs, ISceneApi, ISceneRuleArgs, ISceneSetPropertyArgs, IToggleToolArgs, KbObjectManager, UiObject } from \"@models\";\r\nimport { ClientLogger, KPromise } from \"@rules\";\r\nimport { IMessage, Utils } from \"@tools\";\r\nimport { ILoadSceneArgs, ISceneViewerArgs, SceneViewer } from \"./scene-viewer\";\r\n\r\nexport interface IClaraSceneViewerArgs extends ISceneViewerArgs{\r\n sceneService: ClaraSceneService;\r\n playerUrl: string;\r\n ocLazyLoad: oc.ILazyLoad;\r\n}\r\n\r\nexport class HandlerDb implements IHandlerDb{\r\n constructor(public sceneApi: ISceneApi, public sceneService: ClaraSceneService) {\r\n\r\n }\r\n\r\n // public byHandler: { [handlerId: string]: T } = {};\r\n public byNode: { [nodeId: string]: T[] } = {};\r\n\r\n public clear() {\r\n // this.byHandler = {};\r\n this.byNode = {};\r\n }\r\n\r\n public clearTransient() {\r\n for (let key in this.byNode) {\r\n let h = this.byNode[key];\r\n if (h) {\r\n let removed = h.removeWhere(h1 => h1.addedByRuleType && h1.addedByRuleType.equalsAny(eRuleType.value, eRuleType.scene));\r\n if (removed && removed.length && !h.length) {\r\n delete this.byNode[key];\r\n }\r\n }\r\n }\r\n }\r\n\r\n protected addToDb(id: string, handler: T) {\r\n if (!this.byNode.hasOwnProperty(id)) {\r\n this.byNode[id] = [];\r\n }\r\n this.byNode[id].push(handler);\r\n }\r\n\r\n public add(node: string, handlerId: string, handler: T) {\r\n let hotspotId = (handler as any).hotspotId;\r\n if (hotspotId) {\r\n //for non-mesh hotspots, we just add the hotspot id to the clickdb\r\n this.addToDb(hotspotId, handler);\r\n } else {\r\n let query = this.sceneService.getQueryObject(this.sceneApi, node, null);\r\n let matchingNodes = this.sceneApi.cache.paths.getIds(query);\r\n\r\n matchingNodes.forEach(matchingNode => {\r\n this.addToDb(matchingNode, handler);\r\n });\r\n }\r\n\r\n //add the node id to map to itself\r\n // db.nodeMap[args.modelId] = args.modelId;\r\n //add children of the node to the map\r\n // this.sceneService.getChildNodeIds(this.sceneApi, args.modelId).forEach(i => db.nodeMap[i] = args.modelId);\r\n // }\r\n }\r\n\r\n}\r\n\r\nexport class ClaraSceneRuleArgs implements IClaraSceneRuleArgs {\r\n constructor(public viewer: ClaraViewer) {\r\n this.isMobile = viewer.isMobile;\r\n }\r\n public environment: string;\r\n public company: IDietCompany;\r\n public configurator: Configurator;\r\n public kom: KbObjectManager;\r\n public parentKom: KbObjectManager;\r\n public sceneKom: KbObjectManager;\r\n public sceneApi: ISceneApi;\r\n public isRender: boolean;\r\n public isMobile: boolean;\r\n public clientLanguage: string;\r\n public sceneUtils: ClaraSceneUtilities;\r\n public logs: ClientLogger = new ClientLogger();\r\n // public upload() {\r\n // return this.viewer.upload();\r\n // }\r\n\r\n // TODO: remove in future. It's only here for backwards compatibility. It's true place now is in SceneUtilities\r\n public addModelClickHandler(args: IAddModelClickHandlerArgs) {\r\n this.sceneUtils.addModelClickHandler(args);\r\n }\r\n public addDraggable(args: IDraggable) {\r\n this.sceneUtils.addDraggable(args);\r\n }\r\n public playSceneAnimation(args) {\r\n // DEPRECATED\r\n }\r\n public toggleSceneAnimation() {\r\n // DEPRECATED\r\n }\r\n public sendMessage(msg: IMessage) {\r\n this.viewer.sendMessage(msg);\r\n }\r\n public selectPage(page) {\r\n if (this.viewer.navigateToElement) {\r\n this.viewer.navigateToElement(page);\r\n }\r\n }\r\n public convertCurrency(obj) {\r\n return null;\r\n }\r\n public toggleTool(args: IToggleToolArgs) {\r\n this.viewer.sceneService.toggleTool(this.sceneApi, args);\r\n if (args.tool == \"orbit\") {\r\n this.viewer.sceneConfig.allowOrbit = args.enabled;\r\n }\r\n else if (args.tool == \"pan\") {\r\n this.viewer.sceneConfig.allowPan = args.enabled;\r\n }\r\n else if (args.tool == \"zoom\") {\r\n this.viewer.sceneConfig.allowZoom = args.enabled;\r\n }\r\n }\r\n public constrainCamera(args: IConstrainCameraArgs) {\r\n this.viewer.sceneService.constrainCamera(this.sceneApi, args);\r\n }\r\n public getUploadImageNode(args: IGetUploadImageNodeArgs) {\r\n let a = this.sceneApi.importedImages[this.configurator.name + \"_\" + args.fieldId];\r\n return a ? a.imageNodeId : null;\r\n }\r\n public getTables(args: IGetTableRuleArgs) {\r\n return new KPromise(args.ids.map(tid => this.viewer.tableArraysDb[tid]));\r\n }\r\n}\r\n\r\n\r\nexport class ClaraViewer extends SceneViewer {\r\n constructor(cArgs: IClaraSceneViewerArgs) {\r\n super(cArgs);\r\n this.sceneService = cArgs.sceneService;\r\n this.playerUrl = cArgs.playerUrl;\r\n this.ocLazyLoad = cArgs.ocLazyLoad;\r\n\r\n this.sceneApi = {\r\n isMobile: cArgs.isMobile,\r\n isRender: this.isRender,\r\n clientLanguage: cArgs.clientLanguage,\r\n sceneDb: cArgs.sceneDb,\r\n onSceneNested: (nested: Configurator, nodeId: string) => this.onSceneNested(nested, nodeId),\r\n afterSetProperty: setArgs => this.afterSetProperty(setArgs),\r\n afterAnimateProperty: setArgs => this.afterAnimateProperty(setArgs),\r\n addModelClickHandler: args => this.sceneApi.clickDb.add(args.modelId, args.uniqueId, args),\r\n clearClickHandlers: () => this.sceneApi.clickDb = new HandlerDb(this.sceneApi, this.sceneService),\r\n addDraggable: args => this.sceneApi.draggableDb.add(args.objectId, args.uniqueId, args),\r\n clearDraggables: () => this.sceneApi.draggableDb = new HandlerDb(this.sceneApi, this.sceneService),\r\n sendMessage: (msg) => this.sendMessage(msg),\r\n fetchedScenes: {},\r\n importedImages: {},\r\n getTables: args => new KPromise(args.ids.map(tid => this.tableArraysDb[tid])),\r\n cameraAnimationInProgress: false,\r\n // cameraAnimationPromise: new KPromise(null)\r\n highlights: { user: {}, hover: {}, selection: {} },\r\n selectedNodes: []\r\n };\r\n this.sceneApi.clickDb = new HandlerDb(this.sceneApi, this.sceneService);\r\n this.sceneApi.draggableDb = new HandlerDb(this.sceneApi, this.sceneService);\r\n this.sceneApi.cache = new SceneCache(this.sceneApi);\r\n //this.$scope = this.controllerScope.$new();\r\n this.$scope.hotspotClick = ($event, ann) => this.hotspotClick($event, ann);\r\n this.$scope.hotspotCloseClick = ($event, ann) => this.hotspotCloseClick($event, ann);\r\n // this.$scope.vrMode = false;\r\n // this.$scope.toggleVrMode = () => this.toggleVrMode();\r\n // this.$scope.arMode = false;\r\n // this.$scope.toggleArMode = () => this.toggleArMode();\r\n Utils.supportsVr().then(res => this.$scope.supportsVr = res);\r\n this.$scope.allHotspots = [];\r\n }\r\n\r\n\r\n public sceneService: ClaraSceneService;\r\n public playerUrl: string;\r\n public ocLazyLoad: oc.ILazyLoad;\r\n public sceneApi: ISceneApi; \r\n private hovers: { nodeId: string /*, origMatId: string; hoverMatId: string */ }[] = [];\r\n\r\n /**\r\n * in the form of {annotationId: hotspotId}\r\n */\r\n private annotationToHotspotDb: {} = {};\r\n /**\r\n * stores what scene Id's we've already prefetched so we don't bother prefetching them again. \r\n * Once they are prefetched they are in the browser cache.\r\n */\r\n public prefetchedScenes: { [claraId: string]: any } = {};\r\n /**We have mousedown and click both looking for the same filternodesfromposition result. So we store it on one event loop to not call it multiple times */\r\n public currentFilterNodes: string[];\r\n\r\n public static detectWebGL(): boolean {\r\n try {\r\n let canvas = document.createElement(\"canvas\");\r\n return !!(\r\n (window as any).WebGLRenderingContext &&\r\n (canvas.getContext(\"webgl\") || canvas.getContext(\"experimental-webgl\")));\r\n } catch (e) {\r\n return false;\r\n }\r\n }\r\n\r\n \r\n\r\n public init() {\r\n return this.ocLazyLoad.load(this.playerUrl).then(() => {\r\n // initialize clara viewer\r\n this.createElem(); \r\n let api = claraplayer(this.elem);\r\n this.sceneApi.api = api;\r\n [\"orbit\", \"pan\", \"zoom\", \"home\", \"fullscreen\", \"vrSettings\", \"arMode\"].forEach(s =>\r\n api.player.hideTool(s)); // hide the icons \r\n api.player.removeTool(\"select\");\r\n // turn off the thumbnail\r\n api.player.displayThumbnail(false);\r\n // setup highlighting\r\n this.sceneApi.highlighter = api.selection.setHighlighting(true, { color: this.highlightColor, thickness: 2 });\r\n\r\n /* we use both the customAnnotationFn (for when a hotspot is tied to an annotation) and \r\n useCustomOverlay for hotspots that are tied to other types of nodes.\r\n We can't use useCustomOverlay for both because annotations aren't loaded into the scene \r\n and getScenePosition(idAnnotation) won't work as a result */\r\n api.annotations.useCustomAnnotationFunction((a, d) => this.annotationFn(a, d));\r\n api.annotations.useCustomOverlayFunction(d => this.customOverlayFn(d));\r\n\r\n this.createHotspotElem();\r\n\r\n // add click event\r\n api.player.addTool({\r\n click: event => this.click(event)\r\n }, \"ComponentClick\");\r\n\r\n // add hover event\r\n api.player.addTool({\r\n hover: event => this.hover(event)\r\n }, \"Hover\");\r\n\r\n // add hover event\r\n api.player.addTool({\r\n mousedown: event => this.mousedown(event)\r\n }, \"Mousedown\");\r\n }); \r\n }\r\n\r\n public loadSceneInternal(loadSceneArgs: ILoadSceneArgs): ng.IPromise {\r\n // flush out stuff that needs to be flushed\r\n this.clearHandlers();\r\n this.annotationToHotspotDb = {};\r\n this.sceneApi.cache = new SceneCache(this.sceneApi);\r\n this.sceneApi.highlights = { user: {}, hover: {}, selection: {} };\r\n this.sceneApi.selectedNodes = [];\r\n \r\n let api = this.sceneApi.api;\r\n if (loadSceneArgs.clearMemory) {\r\n this.sceneApi.api.sceneIO.clearScene();\r\n this.sceneApi.fetchedScenes = {}; // clear out the fetched scenes since they were just cleared out of memory\r\n this.sceneApi.importedImages = {};\r\n }\r\n\r\n // toggle tools based on initial scene configurator properties\r\n this.toggleTools();\r\n \r\n if (this.sceneConfig.constrainCameraToRadius) {\r\n this.sceneService.constrainCamera(\r\n this.sceneApi,\r\n {\r\n constrain: this.sceneConfig.constrainCameraToRadius,\r\n radius: this.sceneConfig.cameraRadius\r\n });\r\n }\r\n\r\n // 'rendered' event is when the loading animation is done - we might want to use this when clearing memory\r\n // new loading animation too\r\n // turn thumbnail off with displayThumbnail in player\r\n let rulesRun = false; // to get around a bug in clara where resize causes the loaded event to fire\r\n api.on(\"loaded\", () => {\r\n if (!rulesRun) {\r\n rulesRun = true;\r\n this.sceneApi.hierarchicalVisibility = this.sceneService.isHierarchicalVisibilityEnabled(this.sceneApi);\r\n this.shimThree(this.sceneApi);\r\n\r\n this.runLoadedRule(this.getRuleArgs(eRuleType.sceneLoaded)).then(() => {\r\n if (this.sceneApi.api.commands.isCommandEnabled) {\r\n // need to check armode here because it's calculation is delayed\r\n this.$scope.arEnabled = this.sceneApi.api.commands.isCommandEnabled(\"arMode\");\r\n }\r\n \r\n this.$timeout(() => this.resize(), 0);\r\n // prefetch all scenes so that nested scenes and d&d components load faster\r\n this.prefetchScenes(this.sceneApi);\r\n });\r\n }\r\n });\r\n\r\n this.sceneApi.fetchedScenes[this.sceneConfig.claraId] = api.sceneIO.fetchAndUse(\r\n this.sceneConfig.claraId,\r\n this.scene.publishHash,\r\n { waitForPublish: true }\r\n );\r\n this.prefetchedScenes[this.sceneConfig.claraId] = null;\r\n\r\n return this.loadDeferred.promise;\r\n }\r\n\r\n protected toggleTools()\r\n {\r\n // toggle tools based on initial scene configurator properties\r\n this.sceneService.toggleTool(this.sceneApi, { tool: \"orbit\", enabled: this.sceneConfig.allowOrbit });\r\n this.sceneService.toggleTool(this.sceneApi, { tool: \"pan\", enabled: this.sceneConfig.allowPan });\r\n this.sceneService.toggleTool(this.sceneApi, { tool: \"zoom\", enabled: this.sceneConfig.allowZoom });\r\n if (this.sceneConfig.allowOrbit)\r\n this.sceneApi.api.commands.activateCommand(\"orbit\");\r\n else if (this.sceneConfig.allowPan)\r\n this.sceneApi.api.commands.activateCommand(\"pan\");\r\n else if (this.sceneConfig.allowZoom)\r\n this.sceneApi.api.commands.activateCommand(\"zoom\");\r\n }\r\n\r\n protected runLoadedRule(ruleArgs: ISceneRuleArgs) {\r\n // run the loaded rule of the scene\r\n this.setFieldsIfStandalone();\r\n\r\n return this.ruleService.runRuleTypeAsync(this.sceneConfig, eRuleType.sceneLoaded, ruleArgs).then(loadedRuleResult => {\r\n this.handleRuleError(eRuleType.sceneLoaded, loadedRuleResult);\r\n return this.runRules(false).then(() => {\r\n this.notifyLoaded();\r\n });\r\n });\r\n }\r\n // protected getDragOffset(ev: clara2.IMouseEvent, d: IDraggable): THREE.Vector3 {\r\n // let three = this.sceneService.getThree(this.sceneApi);\r\n // let referPoint = new three.Vector3();\r\n // let offset = new three.Vector3(0, 0, 0);\r\n // let ray: THREE.Ray = void 0;\r\n\r\n // if (d.mode == eDragMode.plane) {\r\n // if (ev.eventRay) {\r\n // ray = ev.eventRay.ray;\r\n // } /*else {\r\n // let rect = this.elem.getBoundingClientRect();\r\n // let ndc = { //normalized device coordinates. x & y should be between -1 and 1\r\n // x: (2 * ev.clientX - rect.width) / rect.width,\r\n // y: (rect.height - 2 * ev.clientY) / rect.height\r\n // };\r\n // ray = store.getTranslator().getCameraMouseRay(ndc).ray;\r\n // }*/\r\n // if (d.mode == eDragMode.plane) {\r\n // let moveOnPlane = new three.Plane();\r\n // let moveOnNormal = new three.Vector3();\r\n // moveOnNormal.set(d.normal.x, d.normal.y, d.normal.z);\r\n // moveOnPlane.set(moveOnNormal, -(d.distanceFromOrigin || 0)); //plane.constant);\r\n // if (!ray.intersectsPlane(moveOnPlane)) return;\r\n\r\n // ray.intersectPlane(moveOnPlane, referPoint);\r\n // }\r\n\r\n // var nodeMatrix = this.sceneApi.api.scene.getWorldTransform(d.$activeNode.id);\r\n // var nodePosition = new three.Vector3().setFromMatrixPosition(nodeMatrix);\r\n // offset = referPoint.sub(nodePosition);\r\n // }\r\n // return offset;\r\n // }\r\n\r\n // /** draggables store the nodes they match, but since they support regex too, at some point we need to run those searches to find the matching nodes to compare against for mouse events */\r\n // protected fillDraggables() {\r\n // let sceneApi = this.sceneApi;\r\n // for (let d of sceneApi.draggables) {\r\n // //get all of the matching node id's to the query provided, and cache for fast retrieval\r\n // if (!d.$matchingNodes) {\r\n // d.$matchingNodes = {};\r\n // let query = this.sceneService.getQueryObject(sceneApi, d.objectId, d.name);\r\n // sceneApi.cache.paths.getIds(query).forEach(id => d.$matchingNodes[id] = {});\r\n // //also get all of the children of the matching nodes\r\n // // for (let mid in d.$matchingNodes) {\r\n // // sceneApi.cache.paths.getIds({ from: mid }).forEach(id => d.$matchingNodes[mid][id] = null);\r\n // // }\r\n // }\r\n // }\r\n // }\r\n\r\n private _clickAlreadyHandled = false; //during drags, the mousedown might initiate the click event. We mark whether it has, so the click handler can ignore.\r\n public mousedown(event: clara2.IMouseEvent) {\r\n let sceneApi = this.sceneApi;\r\n let api = sceneApi.api;\r\n this._clickAlreadyHandled = false;\r\n\r\n //search for draggables\r\n if (Object.keys(sceneApi.draggableDb.byNode).length) {\r\n // this.fillDraggables();\r\n\r\n let hits = this.currentFilterNodes = api.player.filterNodesFromPosition(event);\r\n let hit = hits.first();\r\n\r\n let activeDrag: IDraggable = null;\r\n let activeNodeId = this.sceneService.findAncestorNodeId(\r\n this.sceneApi,\r\n hit,\r\n nid => {\r\n activeDrag = sceneApi.draggableDb.byNode[nid] ? sceneApi.draggableDb.byNode[nid].first() : null;\r\n return activeDrag != null;\r\n }\r\n );\r\n\r\n if (activeDrag) {\r\n //ok we have an active drag, so we select the node\r\n this.sceneService.select(sceneApi, { id: activeNodeId });\r\n let dragStarted = false;\r\n let sceneUtils = this.sceneService.getSceneUtilities(sceneApi, eRuleType.scene, {}, null);\r\n let dragNode = activeDrag.$activeNode = sceneUtils.getNode({ id: activeNodeId });\r\n let three = this.sceneService.getThree(sceneApi);\r\n let startPos = (new three.Vector3()).setFromMatrixPosition(api.scene.getWorldTransform(activeNodeId));\r\n // let offset = this.getDragOffset(event, activeDrag);\r\n\r\n //console.log({ event: \"beforeDrag\", x: startPos.x, y: startPos.y, z: startPos.z });\r\n //and we start the nodeMove command so they can drag it\r\n api.commands.setCommandOptions('nodeMove', {\r\n displayGizmo: false,\r\n mode: activeDrag.mode,\r\n plane: activeDrag.mode == eDragMode.plane ? { normal: activeDrag.normal, constant: activeDrag.distanceFromOrigin ? -activeDrag.distanceFromOrigin : 0 } : null,\r\n surfaceNodeIds: activeDrag.mode == eDragMode.surface ? (Array.isArray(activeDrag.surfaceNodes) ? activeDrag.surfaceNodes : [activeDrag.surfaceNodes]) : null,\r\n keepOffset: true,\r\n shouldMove: (event, newPos, data) => {\r\n // offset && newPos.sub(offset); // temp fix for clara bug: https://github.com/Exocortex/ExocortexKBMax/issues/208\r\n var hitData = data ? data.first() : null;\r\n var uv = hitData ? hitData.uv : null;\r\n let args = { dragNode, startPos, newPos, allow: true, relativeSurfacePos: uv } as IDragArgs;\r\n if (!dragStarted) {\r\n dragStarted = true;\r\n activeDrag.dragStart && activeDrag.dragStart(args);\r\n //console.log({ event: \"dragStart\", x: args.newPos.x, y: args.newPos.y, z: args.newPos.z });\r\n }\r\n if (activeDrag.dragging && dragStarted) {\r\n activeDrag.dragging(args);\r\n //console.log({ event: \"dragging\", x: args.newPos.x, y: args.newPos.y, z: args.newPos.z });\r\n }\r\n // offset && newPos.add(offset); // temp fix for clara bug: https://github.com/Exocortex/ExocortexKBMax/issues/208\r\n return args.allow;\r\n },\r\n // updatePosition: (newPos, surface) => {\r\n // newPos.sub(offset); // temp fix for clara bug: https://github.com/Exocortex/ExocortexKBMax/issues/208\r\n // let args = { dragNode, startPos, newPos } as IDragArgs;\r\n // if (activeDrag.dragging) {\r\n // activeDrag.dragging(args);\r\n // }\r\n // newPos.add(offset); // temp fix for clara bug: https://github.com/Exocortex/ExocortexKBMax/issues/208\r\n // },\r\n onEnd: (event) => {\r\n this.$timeout(() => {\r\n //if the drag never started, then we don't have a drop event\r\n if (dragStarted) {\r\n let args = { dragNode, allow: true, startPos, newPos: (new three.Vector3()).setFromMatrixPosition(api.scene.getWorldTransform(activeNodeId)), relativeSurfacePos: null } as IDragArgs;\r\n activeDrag.dropped && activeDrag.dropped(args);\r\n //console.log({ event: \"dropped\", x: args.newPos.x, y: args.newPos.y, z: args.newPos.z });\r\n }\r\n this.toggleTools();\r\n sceneApi.activeDrag = null;\r\n this.click(event);\r\n });\r\n }\r\n } as clara2.INodeMoveOptions);\r\n api.commands.runCommand(\"nodeMove\");\r\n } else {\r\n this.sceneService.clearSelection(sceneApi);\r\n this.toggleTools();\r\n sceneApi.activeDrag = null;\r\n }\r\n }\r\n }\r\n\r\n public click(event: clara2.IMouseEvent) {\r\n if (!this._clickAlreadyHandled) {\r\n this._clickAlreadyHandled = true;\r\n this.$timeout(() => {\r\n this.clearAnnotations();\r\n let db = this.sceneApi.clickDb;\r\n //let idsToFilterBy = Object.keys(db.nodeMap);\r\n let nodeIds = this.currentFilterNodes || this.sceneApi.api.player.filterNodesFromPosition(event/*, null, { nodes: idsToFilterBy }*/);\r\n //clear out our stored results\r\n this.currentFilterNodes = null;\r\n if (nodeIds && nodeIds.length) {\r\n let nodeId = nodeIds[0];\r\n if (db) {\r\n // check if this node or any of it's parents have a click event\r\n let parentId: string = nodeId;\r\n while (parentId) {\r\n if (db.byNode.hasOwnProperty(parentId)) {\r\n let sceneUtils = this.sceneService.getSceneUtilities(this.sceneApi, eRuleType.scene, {}, null);\r\n let clickArgs: IClickArgs = { clickedNode: sceneUtils.getNode({ id: parentId }), propogate: false };\r\n db.byNode[parentId].forEach(h => h.handler(clickArgs));\r\n if (!clickArgs.propogate) break;\r\n }\r\n parentId = this.sceneService.getParentNodeId(this.sceneApi, parentId);\r\n }\r\n }\r\n } else {\r\n //empty space was clicked. See if there was a handler put on the root scene node\r\n let rootSceneId = this.sceneService.getRootSceneId(this.sceneApi);\r\n if (db.byNode.hasOwnProperty(rootSceneId)) {\r\n let sceneUtils = this.sceneService.getSceneUtilities(this.sceneApi, eRuleType.scene, {}, null);\r\n let clickArgs: IClickArgs = { clickedNode: sceneUtils.getNode({ id: rootSceneId }), propogate: false };\r\n db.byNode[rootSceneId].forEach(h => h.handler(clickArgs));\r\n }\r\n }\r\n });\r\n }\r\n }\r\n\r\n public hover(event: clara2.IMouseEvent) {\r\n let clickdb = this.sceneApi.clickDb;\r\n let dragdb = this.sceneApi.draggableDb;\r\n if ((Object.keys(clickdb.byNode).length || Object.keys(dragdb.byNode).length) && !this.sceneApi.cameraAnimationInProgress && !this.sceneApi.activeDrag) {\r\n if (this.processingMouseOver) return;\r\n this.processingMouseOver = true;\r\n //let idsToFilterBy = Object.keys(db.nodeMap);\r\n let nodeIds = this.sceneApi.api.player.filterNodesFromPosition(event/*, null, { nodes: idsToFilterBy }*/);\r\n if (nodeIds && nodeIds.length) {\r\n let nodeId = nodeIds[0];\r\n\r\n // find the closest ancestor node with a click handler on it\r\n let hoverParentId = this.sceneService.findAncestorNodeId(\r\n this.sceneApi,\r\n nodeId,\r\n nid => (clickdb.byNode.hasOwnProperty(nid) || dragdb.byNode.hasOwnProperty(nid))\r\n );\r\n if (hoverParentId) {\r\n if (this.hoverParentId != hoverParentId) {\r\n this.clearMouseOver();\r\n this.hoverParentId = hoverParentId;\r\n\r\n // now we have the parent that has the click handler. \r\n // The parent and all of it's children should have their materials changed\r\n this.setMouseOverEffectRecursive(this.sceneApi, hoverParentId);\r\n let handlers = clickdb.byNode[hoverParentId];\r\n handlers && handlers.forEach(arg => { // if this is a hotspot, tell it it's hovered\r\n if (arg.hotspot) arg.hotspot.$hover = true;\r\n });\r\n }\r\n } else {\r\n this.clearMouseOver();\r\n }\r\n } else {\r\n this.clearMouseOver();\r\n }\r\n this.processingMouseOver = false;\r\n } else {\r\n this.clearMouseOver();\r\n }\r\n }\r\n\r\n \r\n public shimThree(sceneApi: ISceneApi) {\r\n let three = sceneApi.api.player.getThree().THREE;\r\n if (!three.$originalUpdateMatrixWorld) {\r\n let umw = three.$originalUpdateMatrixWorld = three.Object3D.prototype.updateMatrixWorld;\r\n }\r\n if (sceneApi.hierarchicalVisibility) {\r\n //THREE traverses from parent down updating the matrix world on every pass\r\n //But it doesn't pay attention to hierarchical visibility\r\n three.Object3D.prototype.updateMatrixWorld = function (force) {\r\n if (!this.visible) return;\r\n three.$originalUpdateMatrixWorld.apply(this, arguments);\r\n };\r\n } else {\r\n three.Object3D.prototype.updateMatrixWorld = three.$originalUpdateMatrixWorld;\r\n }\r\n\r\n /** override updateMatrix to add in a cache for the matrix vectors, so\r\n * we're only rebuilding it when we have to. Makes a big difference on render frame rates\r\n */\r\n three.Object3D.prototype.updateMatrix = function () {\r\n let createdCache = false;\r\n if (!this._positionCache) {\r\n this._positionCache = new three.Vector3();\r\n this._quaternionCache = new three.Quaternion();\r\n this._scaleCache = new three.Vector3(1, 1, 1);\r\n this._visibleCache = this.visible;\r\n createdCache = true;\r\n }\r\n if (createdCache ||\r\n (\r\n !this._positionCache.equals(this.position)\r\n || !this._quaternionCache.equals(this.quaternion)\r\n || !this._scaleCache.equals(this.scale)\r\n || this.visible != this._visibleCache\r\n )) {\r\n this.matrix.compose(this.position, this.quaternion, this.scale);\r\n this.matrixWorldNeedsUpdate = true;\r\n this._positionCache.copy(this.position);\r\n this._quaternionCache.copy(this.quaternion);\r\n this._scaleCache.copy(this.scale);\r\n this._visibleCache = this.visible;\r\n\r\n }\r\n }\r\n }\r\n\r\n public prefetchScenes(sceneApi: ISceneApi) {\r\n Object.keys(sceneApi.sceneDb).forEach(idScene => {\r\n if (!this.prefetchedScenes.hasOwnProperty(sceneApi.sceneDb[idScene].claraId)) {\r\n this.prefetchedScenes[sceneApi.sceneDb[idScene].claraId] = null;\r\n sceneApi.api.sceneIO.prefetch(\r\n sceneApi.sceneDb[idScene].claraId,\r\n sceneApi.sceneDb[idScene].publishHash,\r\n { waitForPublish: true }\r\n );\r\n }\r\n });\r\n }\r\n\r\n public getRuleArgs(ruleType: eRuleType): ClaraSceneRuleArgs {\r\n let args = new ClaraSceneRuleArgs(this);\r\n args.configurator = this.sceneConfig.idProduct ? this.uiConfig : this.sceneConfig;\r\n args.kom = args.configurator.$manager;\r\n args.parentKom = args.configurator.$parentConfigurator ? args.configurator.$parentConfigurator.$manager : null;\r\n args.sceneKom = this.sceneConfig.$manager;\r\n args.sceneApi = this.sceneApi;\r\n args.isRender = this.isRender;\r\n args.sceneUtils = this.sceneService.getSceneUtilities(this.sceneApi, ruleType);\r\n args.clientLanguage = this.clientLanguage;\r\n\r\n return args;\r\n }\r\n \r\n protected resolveHotspotTargetNode(hotspot: Hotspot) {\r\n let idMap = hotspot.$parentConfigurator.$sceneIdMap;\r\n let targetNode = hotspot.targetNode;\r\n if (idMap) {\r\n targetNode = idMap[hotspot.targetNode] || hotspot.targetNode;\r\n }\r\n return targetNode;\r\n }\r\n\r\n protected customOverlayFn(div: HTMLDivElement) {\r\n let db = this.sceneApi.clickDb;\r\n let hotspotProcessed = false;\r\n for (let hotspot of this.$scope.allHotspots) {\r\n if (hotspot.target && hotspot.targetNode && hotspot.visible) {\r\n hotspotProcessed = true;\r\n let resolvedTargetNode = this.resolveHotspotTargetNode(hotspot);\r\n let pos = this.sceneApi.api.scene.getScreenPosition(resolvedTargetNode);\r\n if (pos) {\r\n this.positionHotspot(pos, hotspot);\r\n }\r\n if (hotspot.targetShape == eHotspotShape.mesh && resolvedTargetNode) {\r\n if (!db.byNode.hasOwnProperty(resolvedTargetNode) || !db.byNode[resolvedTargetNode].some(h => h.hotspot == hotspot)) {\r\n this.sceneApi.addModelClickHandler({\r\n modelId: resolvedTargetNode,\r\n uniqueId: hotspot.$uid,\r\n handler: () => this.hotspotClick({} as any, hotspot),\r\n hotspot\r\n });\r\n }\r\n }\r\n }\r\n\r\n if (hotspot.targetShape == eHotspotShape.mesh && !hotspot.visible) {\r\n let resolvedTargetNode = this.resolveHotspotTargetNode(hotspot);\r\n // remove from click db if the hotspot is invisible\r\n if (resolvedTargetNode) {\r\n if (db.byNode[resolvedTargetNode]) {\r\n db.byNode[resolvedTargetNode].removeWhere(a => a.uniqueId == hotspot.$uid);\r\n if (db.byNode[resolvedTargetNode].length == 0) {\r\n delete db.byNode[resolvedTargetNode];\r\n }\r\n }\r\n }\r\n }\r\n }\r\n // call digest manually on this scope instead of scope.$apply because $apply starts \r\n // at the root and digests everything.We only want to affect the hotspots here.\r\n if (hotspotProcessed) { //this can be expensive, so only run if there is something to update\r\n this.$scope.$digest();\r\n }\r\n }\r\n\r\n protected annotationFn(annotation: clara2.IAnnotation, div: HTMLDivElement) {\r\n // we don't call scope.$apply here because it's too slow, and the scope.$apply \r\n // in the customOverlayFn takes care of making sure everything is updated anyways.\r\n // it's better in the customOverlay because that is only called once per global update, \r\n // whereas this is called once for each annotation.\r\n\r\n // find the hotspot\r\n let hotspot: Hotspot = this.annotationToHotspotDb[annotation.id];\r\n // if it's an orphan annotation, then stop searching for it\r\n if (!hotspot && !this.annotationToHotspotDb.hasOwnProperty(annotation.id)) {\r\n hotspot = this.$scope.allHotspots.find(h => h.targetNode == annotation.id);\r\n this.annotationToHotspotDb[annotation.id] = hotspot;\r\n }\r\n\r\n if (hotspot) {\r\n hotspot.alpha = annotation.alpha;\r\n let pos = {\r\n x: annotation.left,\r\n y: annotation.top,\r\n top: annotation.top,\r\n left: annotation.left,\r\n width: 0,\r\n height: 0\r\n } as clara2.IScreenPosition;\r\n this.positionHotspot(pos, hotspot);\r\n }\r\n }\r\n\r\n private hotspotCounter: number = 0;\r\n protected hotspotClick($event: ng.IAngularEvent, hotspot: Hotspot) {\r\n hotspot.open = true;\r\n this.hotspotCounter++;\r\n hotspot.$zindex = this.hotspotCounter;\r\n\r\n if (hotspot.idCamera) {\r\n this.sceneService.animateCamera(this.sceneApi, {\r\n duration: hotspot.animationDuration,\r\n toCameraId: hotspot.idCamera,\r\n easing: hotspot.animationEasing\r\n });\r\n }\r\n let clickDb = this.sceneApi.clickDb;\r\n if (clickDb) {\r\n let nestedNullId = hotspot.$parentConfigurator.$uiConfigurator.$nestedSceneId;\r\n let handlerId = nestedNullId ? nestedNullId + \"-\" + hotspot.id : hotspot.id;\r\n if (clickDb.byNode.hasOwnProperty(handlerId)) {\r\n let clickArgs: IClickArgs = { propogate: false };\r\n clickDb.byNode[handlerId].forEach(h => h.handler(clickArgs));\r\n }\r\n }\r\n\r\n // some hotspot popups start off the screen because the height can't be calculated until it's shown\r\n // so we need to offload to recalculate the hotspot position after the digest\r\n this.$timeout(() => {\r\n let pos = this.sceneApi.api.scene.getScreenPosition(this.resolveHotspotTargetNode(hotspot));\r\n if (pos) {\r\n this.positionHotspot(pos, hotspot);\r\n }\r\n });\r\n }\r\n protected hotspotCloseClick($event: ng.IAngularEvent, hotspot: Hotspot) {\r\n $event.stopPropagation();\r\n hotspot.open = false;\r\n }\r\n\r\n protected clearAnnotations() {\r\n for (let h of this.$scope.allHotspots){\r\n if (h.target && h.allowClose) {\r\n h.open = false;\r\n }\r\n }\r\n }\r\n\r\n // protected toggleVrMode() {\r\n // if (this.$scope.vrMode) {\r\n // this.sceneApi.api.commands.deactivateCommand(\"vrMode\");\r\n // } else {\r\n // this.sceneApi.api.commands.activateCommand(\"vrMode\");\r\n // }\r\n // }\r\n\r\n // protected toggleArMode() {\r\n // if (this.$scope.vrMode) {\r\n // this.sceneApi.api.commands.deactivateCommand(\"arMode\");\r\n // } else {\r\n // this.sceneApi.api.commands.runCommand(\"arMode\");\r\n // // this.sceneApi.api.commands.activateCommand(\"arMode\");\r\n // }\r\n // }\r\n\r\n protected afterSetProperty(setArgs: ISceneSetPropertyArgs) {\r\n // if (setArgs.plug.isEqual(\"material\") && setArgs.operator.isEqual(\"physical\")) {\r\n // let mouseOverMatId = this.hoverMaterialDb.get(setArgs.objectId);\r\n // if (mouseOverMatId) {\r\n // setArgs.objectId = mouseOverMatId;\r\n // this.sceneService.setProperty(this.sceneApi, setArgs);\r\n // }\r\n // }\r\n }\r\n\r\n protected afterAnimateProperty(animateArgs: ISceneAnimationArgs) {\r\n // if (animateArgs.plug.isEqual(\"material\") && animateArgs.operator.isEqual(\"physical\")) {\r\n // let mouseOverMatId = this.hoverMaterialDb.get(animateArgs.objectId);\r\n // if (mouseOverMatId) {\r\n // animateArgs.objectId = mouseOverMatId;\r\n // this.sceneService.animate(this.sceneApi, animateArgs);\r\n // }\r\n // }\r\n }\r\n\r\n protected onSceneNested(nestedConfig: Configurator, nullNodeId: string) {\r\n // setup auto click to select page\r\n if (nestedConfig.$parentConfigurator.nestedSceneClickToSelect) {\r\n this.sceneApi.addModelClickHandler({\r\n modelId: nullNodeId,\r\n uniqueId: Utils.shortId(),\r\n handler: () => {\r\n this.navigateToElement(nestedConfig);\r\n }\r\n });\r\n }\r\n }\r\n\r\n /** the id of the node that has a click handler that is causing the current hover to be active */\r\n private hoverParentId: string;\r\n private processingMouseOver: boolean = false;\r\n\r\n\r\n public clearHandlers() {\r\n this.sceneApi.draggableDb && this.sceneApi.draggableDb.clear();\r\n this.sceneApi.clickDb && this.sceneApi.clickDb.clear();\r\n }\r\n protected clearMouseOver() {\r\n // clear out old mouse over\r\n this.sceneService.clearHighlightsOfType(this.sceneApi, eHighlightType.hover);\r\n this.hovers.clear();\r\n this.hoverParentId = null;\r\n this.elem.style.cursor = \"default\";\r\n for (let h of this.$scope.allHotspots) { h.$hover = false };\r\n }\r\n\r\n // TODO: remove this\r\n protected findAncestorNode(node: clara.INode, callback: (n: clara.INode) => boolean): clara.INode {\r\n let parent = node;\r\n while (parent) {\r\n if (callback(parent)) break;\r\n parent = parent.parentNode();\r\n }\r\n return parent;\r\n }\r\n\r\n\r\n protected setMouseOverEffectRecursive(sceneApi: ISceneApi, nodeId: string) {\r\n if (nodeId) {\r\n let api = sceneApi.api;\r\n let nodeType = api.scene.get({ id: nodeId, property: \"type\" });\r\n this.hovers.push({ nodeId });\r\n this.sceneService.highlight(sceneApi, { id: nodeId, on: true }, eHighlightType.hover);\r\n this.elem.style.cursor = \"pointer\";\r\n }\r\n }\r\n\r\n\r\n // public addModelClickHandler(args: IAddModelClickHandlerArgs) {\r\n // let db = this.sceneApi.clickDb;\r\n // // only add it to the list of handlers if the id doesn't already have a handler associated\r\n // if (!db.byHandler.hasOwnProperty(args.uniqueId)) {\r\n // db.byHandler[args.uniqueId] = args;\r\n // // get all nodes that match the given query\r\n // let query = this.sceneService.getQueryObject(this.sceneApi, args.modelId, null);\r\n // let matchingNodes = this.sceneApi.cache.paths.getIds(query);\r\n\r\n // matchingNodes.forEach(matchingNode => {\r\n // if (!db.byNode.hasOwnProperty(matchingNode)) {\r\n // db.byNode[matchingNode] = [];\r\n // }\r\n // db.byNode[matchingNode].push(args);\r\n // });\r\n // //add the node id to map to itself\r\n // // db.nodeMap[args.modelId] = args.modelId;\r\n // //add children of the node to the map\r\n // // this.sceneService.getChildNodeIds(this.sceneApi, args.modelId).forEach(i => db.nodeMap[i] = args.modelId);\r\n // }\r\n // }\r\n\r\n // public addDraggable(d: IDraggable) {\r\n // let sceneApi = this.sceneApi;\r\n // d.$matchingNodes = {};\r\n // let query = this.sceneService.getQueryObject(sceneApi, d.objectId, d.name);\r\n // sceneApi.cache.paths.getIds(query).forEach(id => d.$matchingNodes[id] = {});\r\n // }\r\n\r\n public resize() {\r\n if (this.$scope.loaded) {\r\n this.sceneApi.api.player.resize();\r\n }\r\n }\r\n\r\n \r\n // public upload(): ng.IPromise {\r\n // // without streamchanges, the upload needs to do the following:\r\n // // 1. Upload the file to kbmax server\r\n // // 2. kbmax server imports the file to a public scene in clara that is strictly for uploads\r\n // // 3. now our client makes a call to importNode into this scene\r\n // // 4. in the callback of importNode, we can finally get back to the rule with the uploaded file\r\n // return this.uploadService.promptUserToChooseFile().then(file => {\r\n // // post the upload to kbmax\r\n // let url = \"api/scenes/upload\";\r\n // let postConfig: ng.IRequestShortcutConfig = {\r\n // transformRequest: angular.identity, // add this to not serialize form data\r\n // // set header to undefined so the browser sets the multipart content type\r\n // headers: { \"Content-Type\": undefined }\r\n // };\r\n // let formData = new FormData();\r\n // formData.append(\"file\", file, file.name);\r\n\r\n // let deferred = this.$q.defer();\r\n // // post the file\r\n // this.$http.post(url, formData, postConfig).then(response => {\r\n // // returns the filename of the new node in the upload scene\r\n // let uploadResult = response.data;\r\n\r\n // // now we need to import the file node from the upload scene into this scene\r\n // clara(\"importNode\", {\r\n // el: this.elem,\r\n // importSceneId: uploadResult.uploadSceneId,\r\n // importSelector: uploadResult.filename,\r\n // parentId: \"%MaterialLibrary\",\r\n // callback: (err, uploadedNode) => {\r\n // if (err) {\r\n // deferred.reject(err);\r\n // } else {\r\n // deferred.resolve(uploadResult.filename);\r\n // }\r\n // }\r\n // } as clara.IImportNodeCommandConfig);\r\n // }, reason => {\r\n // deferred.reject(reason);\r\n // });\r\n\r\n // // alert the user the file is uploading\r\n // this.dialogService && this.dialogService.alert({\r\n // msg: \"Uploading file '\" + file.name + \"'\",\r\n // successMsg: \"'\" + file.name + \"' uploaded successfully\",\r\n // promise: deferred.promise\r\n // });\r\n\r\n // return deferred.promise;\r\n // });\r\n // }\r\n\r\n public runAction(actionName: string): ng.IPromise> {\r\n let args = this.getRuleArgs(eRuleType.action);\r\n return this.runActionRule(actionName, args);\r\n }\r\n\r\n public runFieldAction(elem: UiObject){\r\n let args = this.getRuleArgs(eRuleType.field);\r\n return this.ruleService.runRuleContainerAsync(elem, args).then(res => {\r\n this.handleRuleError(elem.name + \" \" + elem.$type, res);\r\n return res;\r\n });;\r\n }\r\n\r\n public runRules(waitForLoad = true): ng.IPromise {\r\n let promise: ng.IPromise = waitForLoad ? this.loadDeferred.promise : new KPromise(null) as any;\r\n\r\n return promise.then(() => {\r\n this.setFieldsIfStandalone();\r\n\r\n return this.sceneService.runRulesCycle(this.sceneConfig, this.uiConfig, this.getRuleArgs(eRuleType.scene))\r\n .then(result => {\r\n this.sceneService.deleteOrphanedNestedScenes(this.sceneApi, this.uiConfig);\r\n this.handleRuleError(eRuleType.scene, result);\r\n //recalculate all hotspots\r\n this.$scope.allHotspots = this.getAllHotspots();\r\n \r\n return result;\r\n });\r\n });\r\n }\r\n\r\n public importUploadFieldImage(uiConfig: Configurator, field: Field, file?: File): ng.IPromise {\r\n return this.sceneService.importUploadFieldImage(this.sceneApi, uiConfig, field, file);\r\n }\r\n\r\n public snapshot(options: clara2.ISnapshotOptions) {\r\n return new KPromise(this.sceneService.snapshot(this.sceneApi, options)) as any;\r\n }\r\n\r\n public dispose() {\r\n if (this.elem){\r\n this.elem.remove();\r\n this.elem = null;\r\n }\r\n }\r\n}\r\n","import { Dirs } from \"@app/helpers/dirs\";\r\nimport { ApiService } from \"@app/services/api.service\";\r\nimport { DialogService } from \"@app/services/dialog.service\";\r\nimport { RuleService } from \"@app/services/rule.service\";\r\nimport { Configurator, eAlertType, eAutoCompleteSource, eOptionFilterSource, eQueryMode, eSelectSource, eSingleOptionBehavior, eSort, Field, IConfiguratorRuleArgs, IJsResult, IOption, IOptionFilterField, IOptionFilterRuleArgs, IOptionFilterRunArgs, IRootScope, ISceneRuleArgs, ITable, ITableObject, Option, OptionFilter, RuleContainer, Table } from \"@models\";\r\nimport { KPromise } from \"@rules\";\r\nimport { Logger, SearchUtils, Utils } from \"@tools\";\r\n\r\nexport interface IRuleErrorDialogScope extends ng.IScope {\r\n ruleName?: string;\r\n error?: string;\r\n configuratorName?: string;\r\n}\r\n\r\nexport interface IConfiguratorHelperArgs {\r\n $http: ng.IHttpService;\r\n $q: ng.IQService;\r\n api: ApiService;\r\n dialogService: DialogService;\r\n ruleService: RuleService;\r\n tracker: ng.IPromiseTracker;\r\n $rootScope: IRootScope;\r\n getRuleArgs: (config: Configurator, changedField?: Field) => IConfiguratorRuleArgs;\r\n showErrors: () => boolean;\r\n}\r\n\r\n/**\r\n * info class for temporary storage of select table data\r\n */\r\nexport interface IOptionFilterInfo {\r\n filterId: string;\r\n fieldIds: string[];\r\n // tablePromise?: ng.IPromise;\r\n}\r\n\r\n/**\r\n * NOT meant to be used as an angular singleton service. It's a helper for running configurators\r\n */\r\nexport class ConfiguratorHelper {\r\n constructor(public args: IConfiguratorHelperArgs) {\r\n\r\n }\r\n\r\n /** holds info about the option filters, in a structure that orders them by dependency */\r\n public odb: { [idProduct: number]: { [id: string]: IOptionFilterInfo } };\r\n public filterLevelDb: { [idProduct: number]: { [level: number]: string[] } } = {};\r\n /** once the tablespromise resolves, will be filled with the tables converted to arrays \r\n * (for sending in to the rule args) \r\n */\r\n public tableArraysDb: { [id: number]: ITableObject } = {};\r\n public allOptionFilterRules: Function;\r\n\r\n public downloadTables(tableIds: number[]): ng.IPromise {\r\n if (tableIds.length) {\r\n return this.args.api.tables.getBatch({ ids: tableIds }, this.args.tracker).then(data => {\r\n this.loadTables(data);\r\n });\r\n } else {\r\n return this.args.$q.when(null);\r\n }\r\n }\r\n\r\n public loadTables(itables: ITable[]) {\r\n itables.forEach(t => {\r\n let table = new Table(t);\r\n this.tableArraysDb[table.id] = table.toObjectArray();\r\n });\r\n }\r\n\r\n public handleRuleError(\r\n ruleName: string,\r\n result: IJsResult\r\n ) {\r\n if (result && result.hasError && this.args.showErrors()) {\r\n let dialogScope: IRuleErrorDialogScope = this.args.$rootScope.$new();\r\n dialogScope.ruleName = ruleName;\r\n dialogScope.configuratorName = result.parameters.configurator.name;\r\n dialogScope.error = result.error.message;\r\n this.args.dialogService.alert({\r\n type: eAlertType.error,\r\n template: Dirs.view(\"alert-rule-error\"),\r\n scope: dialogScope,\r\n persist: true\r\n });\r\n }\r\n }\r\n\r\n public runRuleContainerAsync(\r\n ruleContainer: RuleContainer,\r\n args?: T\r\n ): ng.IPromise> {\r\n console.log('run rule async', ruleContainer);\r\n return this.args.ruleService.runRuleContainerAsync(ruleContainer, args || this.args.getRuleArgs(ruleContainer.$parentConfigurator) as T).then(res => {\r\n this.handleRuleError(ruleContainer.name + \" \" + ruleContainer.$type, res);\r\n return res;\r\n });\r\n }\r\n\r\n public runRuleContainerSync(\r\n ruleContainer: RuleContainer,\r\n args?: T\r\n ): IJsResult {\r\n let res = this.args.ruleService.runRuleContainerSync(ruleContainer, args || this.args.getRuleArgs(ruleContainer.$parentConfigurator) as T);\r\n this.handleRuleError(ruleContainer.name + \" \" + ruleContainer.$type, res);\r\n return res;\r\n }\r\n\r\n\r\n public runRuleTypeAsync(\r\n config: Configurator,\r\n ruleType: string,\r\n args?: T\r\n ): ng.IPromise> {\r\n return this.args.ruleService.runRuleTypeAsync(config, ruleType, args || this.args.getRuleArgs(config) as T).then(res => {\r\n this.handleRuleError(ruleType, res);\r\n return res;\r\n });\r\n }\r\n\r\n public runActionByIdAsync(\r\n config: Configurator,\r\n actionId: string,\r\n args?: T\r\n ): ng.IPromise> {\r\n return this.args.ruleService.runActionRuleByIdAsync(config as Configurator, actionId, args || this.args.getRuleArgs(config) as T)\r\n .then(res => {\r\n this.handleRuleError(actionId, res);\r\n return res;\r\n });\r\n }\r\n\r\n public runOptionFilterSourceRule() {\r\n \r\n }\r\n \r\n\r\n public autoCompleteQuery(query: string, field: Field) {\r\n if (query) {\r\n if (field.autoCompleteSource == eAutoCompleteSource.table) {\r\n // return this.tablesPromise.then(() => {\r\n let arr = this.tableArraysDb[field.idTable].data;\r\n let results = SearchUtils.search(\r\n query, arr,\r\n item => item[Utils.scrubName(field.labelColumn || field.valueColumn)]);\r\n let scrubValueCol = Utils.scrubName(field.valueColumn);\r\n let scrubLabelCol = Utils.scrubName(field.labelColumn);\r\n let scrubImageCol = Utils.scrubName(field.imageColumn);\r\n // map the results to options\r\n let options = results.map(item => {\r\n let o = new Option();\r\n o.value = item[scrubValueCol];\r\n o.label = item[scrubLabelCol];\r\n o.image = item[scrubImageCol];\r\n return o;\r\n });\r\n return this.args.$q.when(options);\r\n // });\r\n } else if (field.autoCompleteSource == eAutoCompleteSource.database) {\r\n return this.args.api.products.autocomplete(\r\n field.$parentConfigurator.idProduct, field.id, query, this.args.tracker);\r\n }\r\n }\r\n return this.args.$q.when([]);\r\n }\r\n\r\n public autoCompleteGetLabel(value: any, field: Field) {\r\n if (field.labelColumn) {\r\n // when autocomplete fields are using the labelColumn, then when they are first opening,\r\n // they will request for the label of their current value\r\n if (field.autoCompleteSource == eAutoCompleteSource.table) {\r\n let scrubValueCol = Utils.scrubName(field.valueColumn);\r\n let scrubLabelCol = Utils.scrubName(field.labelColumn);\r\n let scrubImageCol = Utils.scrubName(field.imageColumn);\r\n\r\n // return this.tablesPromise.then(() => {\r\n let arr = this.tableArraysDb[field.idTable].data;\r\n let row = arr.find(item => item[scrubValueCol] === value);\r\n return row ? row[scrubLabelCol] : null;\r\n // });\r\n } else if (field.autoCompleteSource == eAutoCompleteSource.database) {\r\n\r\n }\r\n }\r\n\r\n return value;\r\n }\r\n\r\n public getOptionFilterSource(filter: OptionFilter): any[] {\r\n let arr: any[] = [];\r\n if (filter.source == eOptionFilterSource.table) {\r\n let tableObject = this.tableArraysDb[filter.idTable];\r\n if (tableObject) arr = tableObject.data;\r\n } else if (filter.source == eOptionFilterSource.optionFilter) {\r\n let f = filter.$parentConfigurator.$manager.get(filter.idOptionFilter) as OptionFilter;\r\n arr = f ? f.$source : [];\r\n } else { //must be a query\r\n // get the source table by running the query\r\n let ruleArgs: IOptionFilterRuleArgs = this.args.getRuleArgs(filter.$parentConfigurator);\r\n arr = this.runRuleContainerSync(filter, ruleArgs).parameters.source;\r\n }\r\n if (arr == null) throw new Error(`Could not find source for option filter '${filter.name}'`);\r\n filter.$source = arr;\r\n return arr;\r\n }\r\n\r\n public shouldRunOptionFilter(config: Configurator, filter: OptionFilter) {\r\n let shouldRun = true;\r\n if (config.v >= 1 && filter.optimized) { // older configurators will not have the needed info for optimization\r\n let last = filter.$lastValues;\r\n if (last) { // if it has lastReferenceValues then it has already been run\r\n shouldRun = Object.keys(last).some(fieldId => {\r\n let field = config.$manager.get(fieldId);\r\n if (field.isArrayType()) {\r\n return !(field.value as any[]).equals(last[fieldId]);\r\n } else {\r\n return (last[fieldId] != field.value);\r\n }\r\n });\r\n }\r\n }\r\n // if this filter is sourced from another option filter, we need to also check if that option filter\r\n // needed to be run in this cycle\r\n if (filter.source == eOptionFilterSource.optionFilter ||\r\n (filter.source == eOptionFilterSource.query && filter.queryMode == eQueryMode.optionFilter)\r\n ) {\r\n let otherFilter = config.$manager.get(filter.idOptionFilter) as OptionFilter;\r\n shouldRun = otherFilter.$shouldRun || shouldRun;\r\n } else if (filter.source == eOptionFilterSource.query && filter.queryMode == eQueryMode.parentOptionFilter) {\r\n let otherFilter = config.$parentConfigurator.$manager.get(filter.idOptionFilter) as OptionFilter;\r\n shouldRun = otherFilter.$shouldRun || shouldRun;\r\n }\r\n filter.$shouldRun = shouldRun;\r\n return shouldRun;\r\n }\r\n\r\n public runOptionFilter(config: Configurator, s: IOptionFilterInfo) {\r\n let filter = config.$manager.get(s.filterId);\r\n // optimize by not running if all the inputs are the same as last time it was run\r\n let shouldRun = this.shouldRunOptionFilter(config, filter);\r\n\r\n if (shouldRun) {\r\n this._optionFilterRunCount++;\r\n\r\n let source = this.getOptionFilterSource(filter);\r\n let clientLang = this.args.$rootScope.clientLanguage;\r\n let shouldTranslate = (clientLang != this.args.$rootScope.companySettings.defaultLanguage);\r\n\r\n // start with full table. //Use int array and preallocate it for performance reasons\r\n let matchedRows: number[] = [];\r\n for (let r = 0; r < source.length; r++) {\r\n matchedRows.push(r);\r\n }\r\n\r\n for (let f = 0; f < s.fieldIds.length; f++) {\r\n // get the real field from this configurator\r\n let field = config.$manager.get(s.fieldIds[f]);\r\n let fieldBaseType = field.getBaseType();\r\n let fieldIsArray = field.isArrayType();\r\n\r\n let newOptions: IOption[] = [];\r\n let scrubValueCol = Utils.scrubName(field.valueColumn);\r\n let scrubLabelCol = Utils.scrubName(field.labelColumn);\r\n let scrubSortCol = Utils.scrubName(field.sortColumn);\r\n let scrubTranslateCol = shouldTranslate ? \r\n (scrubLabelCol ?\r\n scrubLabelCol + clientLang.toUpperCase()\r\n : scrubValueCol + clientLang.toUpperCase())\r\n : \"\";\r\n let scrubImageCol = Utils.scrubName(field.imageColumn);\r\n let scrubImageWhenSelectedCol = Utils.scrubName(field.imageWhenSelectedColumn);\r\n let scrubDescCol = Utils.scrubName(field.descriptionColumn);\r\n var scrubDescTranslateCol = shouldTranslate ? (scrubDescCol + clientLang.toUpperCase()) : \"\";\r\n\r\n // fill in options... we only want unique options\r\n let uniqueDb: { [value: string]: IOption } = {};\r\n for (let rowIndex of matchedRows) {\r\n let row = source[rowIndex];\r\n if (!uniqueDb[row[scrubValueCol]]) {\r\n let entry = {\r\n label: row.hasOwnProperty(scrubTranslateCol) ? row[scrubTranslateCol] : row[scrubLabelCol],\r\n image: row[scrubImageCol],\r\n imageWhenSelected: row[scrubImageWhenSelectedCol],\r\n description: row.hasOwnProperty(scrubDescTranslateCol) ? row[scrubDescTranslateCol] : row[scrubDescCol],\r\n value: Field.convertToType(row[scrubValueCol], fieldBaseType, field.precision),\r\n sort: row[scrubSortCol]\r\n } as IOption;\r\n uniqueDb[row[scrubValueCol]] = entry;\r\n newOptions.push(entry)\r\n } \r\n }\r\n\r\n // sort if applicable\r\n let sortCol = field.sortColumn ? \"sort\" : (field.labelColumn ? \"label\" : \"value\");\r\n if (field.sort == eSort.ascending) {\r\n newOptions.sortBy(o => o[sortCol]);\r\n } else if (field.sort == eSort.descending) {\r\n newOptions.sortByDescending(o => o[sortCol]);\r\n }\r\n\r\n // set the new options all at once\r\n field.options = newOptions;\r\n\r\n this.handleSingleOption(field, filter);\r\n\r\n // now recalculate the matched rows for the next field\r\n if (f !== s.fieldIds.length - 1) {\r\n matchedRows = matchedRows.filter(rowIndex => {\r\n let cellValue = source[rowIndex][scrubValueCol];\r\n cellValue = Field.convertToType(cellValue, fieldBaseType, field.precision);\r\n return fieldIsArray ? (field.value as any[]).contains(cellValue) : (cellValue == field.value);\r\n });\r\n }\r\n }\r\n\r\n this.storeLastValuesFor(config, s);\r\n }\r\n }\r\n\r\n public handleSingleOption(field: Field, optionFilter: OptionFilter) {\r\n // if there is only one option left, check the specified behavior on the option filter\r\n if (optionFilter.singleOptionBehavior == eSingleOptionBehavior.disable) {\r\n field.enabled = (field.options.length > 1);\r\n } else if (optionFilter.singleOptionBehavior == eSingleOptionBehavior.hide) {\r\n field.visible = (field.options.length > 1);\r\n }\r\n }\r\n\r\n private _optionFilterRunCount = 0;\r\n\r\n protected storeLastValuesFor(config: Configurator, s: IOptionFilterInfo) {\r\n if (config.v >= 1) { // older configurators will not have the needed info for optimization\r\n // store last field values for optimization\r\n let filter = config.$manager.get(s.filterId);\r\n let last = filter.$lastValues = filter.$lastValues || {};\r\n filter.fieldReferences.forEach(fieldId => {\r\n let field = config.$manager.get(fieldId);\r\n if (field.isArrayType()) {\r\n last[fieldId] = (field.value as any[]).map(v => v);\r\n } else {\r\n last[fieldId] = field.value;\r\n }\r\n });\r\n s.fieldIds.forEach(fieldId => {\r\n let field = config.$manager.get(fieldId);\r\n if (field.isArrayType()) {\r\n last[field.id] = (field.value as any[]).map(v => v);\r\n } else {\r\n last[field.id] = field.value;\r\n }\r\n });\r\n }\r\n }\r\n\r\n public runSelects(config: Configurator): ng.IPromise {\r\n let promise: ng.IPromise = (new KPromise(null)) as any;\r\n if (!config.optionFilters.length) return promise; //shortcircuit if there is nothing to do here\r\n\r\n config.$freezeFieldValueCalculation = true; // freeze field value calculation for perf\r\n\r\n let startTime = Date.now();\r\n this._optionFilterRunCount = 0;\r\n // fill in the db\r\n if (!this.odb) this.odb = {};\r\n\r\n if (!this.odb[config.idProduct]) {\r\n this.odb[config.idProduct] = {};\r\n this.filterLevelDb[config.idProduct] = {};\r\n // loop through each select table, find all registered fields\r\n let allFields = config.getFields(f => f.canJoinOptionFilter() && f.selectSource == eSelectSource.optionFilter);\r\n config.optionFilters.forEach(o => {\r\n let info: IOptionFilterInfo = {\r\n filterId: o.id,\r\n fieldIds: allFields.filter(f => f.idOptionFilter == o.id).map(f => f.id)\r\n };\r\n\r\n this.odb[config.idProduct][o.id] = info;\r\n });\r\n\r\n // filters are organized by level of dependencies. Those at a level of 1 have no dependencies\r\n // so we just roll through the filters, and make a jagged array where the primary index is \r\n // the level, and we loop them and run them\r\n config.optionFilters.forEach(filter => {\r\n let arr = this.filterLevelDb[config.idProduct][filter.level];\r\n if (!arr) this.filterLevelDb[config.idProduct][filter.level] = [];\r\n this.filterLevelDb[config.idProduct][filter.level].push(filter.id);\r\n });\r\n //// fill in start filters also\r\n // this.startFilters = config.optionFilters.filter(f => !f.dependsOn || f.dependsOn.length == 0);\r\n }\r\n\r\n // if any of the option filters in the configurator are sourced by a database, then we just have the server\r\n // do all the figuring\r\n if (!config.filtersShouldRunOnClient()) {\r\n /* another level of optimization... if all the fields referenced by option filters in their query \r\n rule and fields in the option filter haven't changed value, then there is no reason to call the server */\r\n let shouldRun = true;\r\n if (config.v >= 1) { // older configurators will not have the needed info for optimization\r\n for (let filter of config.optionFilters) {\r\n shouldRun = this.shouldRunOptionFilter(config, filter);\r\n if (shouldRun) break;\r\n }\r\n }\r\n\r\n if (shouldRun) {\r\n let fieldOptions: IOptionFilterField[] = [];\r\n config.optionFilters.forEach(filter => {\r\n this.odb[config.idProduct][filter.id].fieldIds.forEach(fieldId => {\r\n let field = config.$manager.get(fieldId);\r\n fieldOptions.push({ id: field.id, name: field.name, options: field.options });\r\n });\r\n });\r\n let lastValues = {};\r\n config.optionFilters.forEach(filter => {\r\n lastValues[filter.id] = filter.$lastValues;\r\n });\r\n let runArgs = {\r\n configuredProduct: config.getConfiguredProduct(true),\r\n lastValues,\r\n fieldOptions\r\n } as IOptionFilterRunArgs;\r\n promise = this.args.api.optionFilters.run(runArgs, this.args.tracker).then(r => {\r\n r.filters.forEach(filterResult => {\r\n filterResult.fields.forEach(f => {\r\n let field = config.$manager.get(f.id);\r\n let filter = config.$manager.get(filterResult.id);\r\n // sort if applicable\r\n let sortCol = field.sortColumn ? \"sort\" : (field.labelColumn ? \"label\" : \"value\");\r\n if (field.sort == eSort.ascending) {\r\n f.options.sortBy(o => o[sortCol]);\r\n } else if (field.sort == eSort.descending) {\r\n f.options.sortByDescending(o => o[sortCol]);\r\n }\r\n\r\n field.options = f.options;\r\n\r\n this.handleSingleOption(field, filter);\r\n });\r\n });\r\n\r\n // store optimization info\r\n r.filters.forEach(filter => this.storeLastValuesFor(config, this.odb[config.idProduct][filter.id]));\r\n });\r\n }\r\n } else {\r\n /* we have all tables, and no databases, so we operate locally to avoid a roundtrip to the server\r\n because getTables is a KPromise that isn't a real promise, we can run these as if they were \r\n sync (because they are) */\r\n let level = 1;\r\n while (true) {\r\n let filterIds = this.filterLevelDb[config.idProduct][level];\r\n if (filterIds) {\r\n filterIds.forEach(filterId => {\r\n this.runOptionFilter(config, this.odb[config.idProduct][filterId]);\r\n });\r\n level++;\r\n } else {\r\n break;\r\n }\r\n }\r\n\r\n promise = (new KPromise(null)).then(() => {\r\n // store optimization info\r\n config.optionFilters.forEach(filter => this.storeLastValuesFor(config, this.odb[config.idProduct][filter.id]));\r\n }) as any;\r\n }\r\n\r\n return promise.then(() => {\r\n config.$freezeFieldValueCalculation = false;\r\n Logger.logRuleEnd(config.name, `option filters (${this._optionFilterRunCount})`, startTime);\r\n });\r\n }\r\n}\r\n","import type { TransformNode } from '@babylonjs/core/Meshes/transformNode';\r\nimport * as kb3d from '@kb3d';\r\nimport {\r\n applyTransformToSpace,\r\n IKb3dPointerArgs,\r\n IKeyboardArgs,\r\n isAnnotation,\r\n isSpaceNode,\r\n Kb3dObject,\r\n KbColor,\r\n KbQuaternion,\r\n MaterialNode,\r\n SceneNode,\r\n SpaceNode\r\n} from '@kb3d';\r\nimport {\r\n Configurator,\r\n eAlertType,\r\n eColorFormat,\r\n eEnvironment,\r\n eHotspotShape,\r\n eRuleType,\r\n Field,\r\n Hotspot,\r\n IColorOperationArgs,\r\n IGetTableRuleArgs,\r\n IHotspotClickArgs,\r\n IJsResult,\r\n IKb3dActivateGizmoArgs,\r\n IKb3dActivateSketchArgs,\r\n IKb3dAdBoundingboxWatcherArgs,\r\n IKb3dAddClickHandlerArgs,\r\n IKb3dAddHotspotClickHandlerArgs,\r\n IKb3dAnimateArgs,\r\n IKb3dCallSceneFunctionArgs,\r\n IKb3dClearHandlerArgs,\r\n IKb3dCloneNodeArgs,\r\n IKb3dCreateNodeArgs,\r\n IKb3dCreateSketchPathArgs,\r\n IKb3dGetChildrenOfTypeArgs,\r\n IKb3dGetPropertyArgs,\r\n IKb3dHighlightArgs,\r\n IKb3dSetPropertyArgs,\r\n ISceneRuleArgs,\r\n ISetParentArgs,\r\n KbObjectManager,\r\n UiObject,\r\n} from '@models';\r\nimport { ClientLogger, KPromise } from '@rules';\r\nimport { Color, IMessage, Utils } from '@tools';\r\nimport { ILoadSceneArgs, ISceneViewerArgs, SceneViewer } from './scene-viewer';\r\n\r\nconst SCENE_CLICK_HANDLER_TAG = 'scene_click';\r\nexport class Kb3dViewer extends SceneViewer {\r\n constructor(private cArgs: ISceneViewerArgs) {\r\n super(cArgs);\r\n this.enableScreenshots = cArgs.enableScreenshots || false;\r\n //this.sceneService = args.$injector.get(Token.ClaraSceneService.key);\r\n //this.$scope = cArgs.controllerScope.$new();\r\n this.$scope.hotspotClick = ($event, ann) => this.hotspotClick($event, ann);\r\n this.$scope.hotspotCloseClick = ($event, ann) => this.hotspotCloseClick($event, ann);\r\n this.$scope.arActive = () => this.viewer.ar.xrActive;\r\n this.$scope.toggleAr = () => this.toggleAr();\r\n this.$scope.arEnabled = true;\r\n Utils.supportsVr().then(res => (this.$scope.supportsVr = res));\r\n this.$scope.allHotspots = [];\r\n }\r\n\r\n viewer: kb3d.KbViewer;\r\n sceneNode: kb3d.SceneNode;\r\n lastDeploy: number;\r\n enableScreenshots: boolean;\r\n\r\n public init() {\r\n this.createElem();\r\n\r\n this.viewer = new kb3d.KbViewer({\r\n container: this.elem,\r\n highlightColor: this.highlightColor ? KbColor.FromIntObject(new Color(this.highlightColor).toRgb()) : null,\r\n webworkerPath:\r\n this.clusterEnv === 'dev'\r\n ? `${this.assetRoot}/worker3d.js`\r\n : `${this.assetRoot}/worker3d.min.js?v=${this.cacheBuster}`,\r\n debugMode: this.clusterEnv === 'dev',\r\n forceDisableGraphicsOptimization: this.isRender,\r\n enableScreenshots: this.enableScreenshots,\r\n });\r\n\r\n this.elem.addEventListener('kb3d.scenePropertyChange', (e: CustomEvent) => {\r\n if ('arEnabled' in e.detail) {\r\n const arEnabled = e.detail['arEnabled'];\r\n this.$scope.$apply(() => {\r\n this.$scope.arEnabled = arEnabled;\r\n });\r\n }\r\n });\r\n\r\n this.createHotspotElem();\r\n this.viewer.viewChanged.subscribe(() => this.updateHotspots(true));\r\n this.viewer.interaction.onKeyboard.subscribe(k => this.onKeyboard(k));\r\n\r\n return new KPromise(null) as any as ng.IPromise;\r\n }\r\n\r\n public dispose() {\r\n if (this.viewer) {\r\n this.viewer.gizmos.clearGizmo();\r\n this.viewer.dispose();\r\n }\r\n if (this.sceneNode && this.sceneNode._manager) {\r\n this.sceneNode._manager.clickHandlers.deleteByTag(SCENE_CLICK_HANDLER_TAG);\r\n }\r\n if (this.elem) {\r\n this.elem.remove();\r\n this.elem = null;\r\n }\r\n }\r\n\r\n public loadSceneInternal(args: ILoadSceneArgs): ng.IPromise {\r\n let manager = new kb3d.Kb3dManager({\r\n assetRoot: this.assetRoot,\r\n forceFullSizeTextures: args.isRenderContext || false,\r\n environment: {\r\n lastDeploy: this.lastDeploy,\r\n cacheBuster: this.cacheBuster,\r\n },\r\n }); //default services automatically used\r\n this.sceneNode = manager.deserialize(this.scene.graph);\r\n this.$scope.arEnabled = !!this.sceneNode.arEnabled;\r\n this.$scope.fullscreenEnabled = !!this.sceneNode.fullscreenEnabled;\r\n args.config.$sceneNode = this.sceneNode;\r\n this.sceneNode._configurator = args.config;\r\n\r\n //args.loadingExperience is set to false in render.ts to disable loading experiences for renders\r\n if (args.loadingExperience === false) {\r\n this.viewer.loadScene({\r\n sceneNode: this.sceneNode,\r\n loadingExperience: kb3d.eLoadingExperience.none,\r\n deferLoadingPromise: this.$q.all([this.loadDeferred.promise, this.configuratorLoadedPromise]) as any,\r\n });\r\n } else {\r\n this.viewer.loadScene({\r\n sceneNode: this.sceneNode,\r\n deferLoadingPromise: this.$q.all([this.loadDeferred.promise, this.configuratorLoadedPromise]) as any,\r\n });\r\n }\r\n\r\n manager.clickHandlers.add(this.sceneNode, SCENE_CLICK_HANDLER_TAG, p => {\r\n this.onSceneClick(p);\r\n });\r\n\r\n return this.runRules(false).then(() => {\r\n this.notifyLoaded();\r\n });\r\n }\r\n\r\n public runRules(waitForLoad = true): ng.IPromise {\r\n let promise: ng.IPromise = waitForLoad ? this.loadDeferred.promise : (new KPromise(null) as any);\r\n\r\n return promise\r\n .then(() => {\r\n let ruleArgs = this.getRuleArgs(eRuleType.scene);\r\n this.setFieldsIfStandalone();\r\n\r\n // before running the value rules, we need to clear out transient handlers\r\n this.clearTransientHandlers(this.sceneNode, eRuleType.value);\r\n\r\n let runUiRules = !this.sceneDb[this.sceneConfig.idScene].idProduct;\r\n if (runUiRules) {\r\n // run the value rule first\r\n // ruleArgs.sceneUtils.ruleType = eRuleType.value;\r\n return this.runRuleTypeAsync(\r\n this.sceneConfig,\r\n eRuleType.value,\r\n this.getRuleArgs(eRuleType.value)\r\n ).then(() => {\r\n this.sceneConfig.preValidate();\r\n this.sceneConfig.isValid();\r\n });\r\n }\r\n })\r\n .then(() => {\r\n return this.runSceneRules(this.sceneConfig, this.uiConfig, this.getRuleArgs(eRuleType.scene), false);\r\n })\r\n .then(result => {\r\n this.handleRuleError(eRuleType.scene, result);\r\n //recalculate all hotspots\r\n this.$scope.allHotspots = this.getAllHotspots();\r\n this.updateHotspots(false);\r\n\r\n return result;\r\n });\r\n }\r\n\r\n protected clearTransientHandlers(sceneNode: SceneNode, ...ruleTypes: eRuleType[]) {\r\n let m = sceneNode._manager;\r\n let handlerMaps = [m.clickHandlers, m.doubleClickHandlers, m.draggables, m.hotspotClickHandlers];\r\n for (let hm of handlerMaps) {\r\n hm.deleteByTag(...ruleTypes);\r\n }\r\n }\r\n\r\n protected runSceneRules(\r\n sceneConfig: Configurator,\r\n uiConfig: Configurator,\r\n ruleArgs: Kb3dSceneRuleArgs,\r\n skipRulesIfNoNestedSceneChanges: boolean\r\n ): ng.IPromise> {\r\n let nestedSceneRulesWereRun = false;\r\n\r\n return this.runNestedSceneRules(uiConfig)\r\n .then((r: any[]) => {\r\n nestedSceneRulesWereRun = r && r.some(r2 => r2 != null);\r\n if (!sceneConfig.$ranLoadedRule) {\r\n sceneConfig.$ranLoadedRule = true;\r\n skipRulesIfNoNestedSceneChanges = false;\r\n ruleArgs.ruleType = eRuleType.sceneLoaded;\r\n return this.runRuleTypeAsync(sceneConfig, eRuleType.sceneLoaded, ruleArgs);\r\n }\r\n })\r\n .then(() => {\r\n this.deleteOrphanedNestedScenes(uiConfig);\r\n if (!skipRulesIfNoNestedSceneChanges || nestedSceneRulesWereRun) {\r\n //skip running the rules if there were no nested scene rules run\r\n this.clearTransientHandlers(ruleArgs.sceneNode, eRuleType.scene);\r\n ruleArgs.ruleType = eRuleType.scene;\r\n return this.runRuleTypeAsync(sceneConfig, eRuleType.scene, ruleArgs).then(ruleResult => {\r\n uiConfig.$fieldsDirtyForSceneRules = false;\r\n return ruleResult;\r\n });\r\n }\r\n });\r\n }\r\n\r\n public runNestedSceneRules(uiConfig: Configurator) {\r\n let nestedConfigs = uiConfig.getNestedConfigurators();\r\n\r\n if (nestedConfigs.length) {\r\n let promises: ng.IPromise[] = [];\r\n // loop through nested configurators, merge the scenes if they haven't been already, and run their rules\r\n nestedConfigs.forEach(nested => {\r\n if (nested.idScene) {\r\n let refConfig = uiConfig.referencedConfigurators.find(rc => rc.idProduct == nested.idProduct);\r\n if (refConfig.nestScene) {\r\n // create the scene configurator for the nested configurator if it doesn't already exist\r\n // (or has been swapped for another scene)\r\n if (!nested.$sceneConfigurator || nested.$sceneConfigurator.idScene != nested.idScene) {\r\n nested.$sceneConfigurator = new Configurator(\r\n new KbObjectManager(),\r\n this.sceneDb[nested.idScene].configurator\r\n );\r\n }\r\n nested.$sceneConfigurator.$uiConfigurator = nested;\r\n nested.$nestHotspots = refConfig.nestHotspots;\r\n // in case the nested scene is a standalone scene, we need to set it's fields from the uiConfig\r\n nested.$sceneConfigurator.setFields(nested.getFieldsObject());\r\n\r\n let skipRules =\r\n !nested.$fieldsDirtyForSceneRules && (!nested.alwaysChild || !nested.alwaysChildOf);\r\n\r\n this.nestScene(\r\n // merge the scene if it hasn't already been merged\r\n uiConfig.$sceneNode as kb3d.SceneNode,\r\n nested\r\n );\r\n\r\n promises.push(\r\n // now run the rules on the nested scene\r\n this.runSceneRules(\r\n nested.$sceneConfigurator,\r\n nested,\r\n this.getNestedSceneRuleArgs(nested, nested.$sceneConfigurator, eRuleType.scene),\r\n skipRules\r\n )\r\n );\r\n }\r\n }\r\n });\r\n return this.$q.all(promises);\r\n } else {\r\n return new KPromise(null) as any;\r\n }\r\n }\r\n\r\n protected nestScene(parentSceneNode: SceneNode, nested: Configurator) {\r\n if (!nested.$sceneNode) {\r\n //nested scene has already been created so skip\r\n let ser = this.sceneDb[nested.idScene];\r\n let nestedSceneNode = parentSceneNode._manager.nestScene(nested.name, parentSceneNode, ser.graph as any);\r\n nested.$sceneNode = nestedSceneNode;\r\n nestedSceneNode._configurator = nested;\r\n\r\n //add automatic click to navigate if enabled\r\n if (nested.$parentConfigurator.nestedSceneClickToSelect) {\r\n parentSceneNode._manager.clickHandlers.add(nestedSceneNode, undefined, () => {\r\n this.navigateToElement(nested);\r\n });\r\n }\r\n }\r\n }\r\n\r\n public runRuleTypeAsync(\r\n config: Configurator,\r\n ruleType: string,\r\n args?: T\r\n ): ng.IPromise> {\r\n return this.ruleService.runRuleTypeAsync(config, ruleType, args).then(res => {\r\n this.handleRuleError(ruleType, res);\r\n return res;\r\n });\r\n }\r\n\r\n protected deleteOrphanedNestedScenes(uiConfig: Configurator) {\r\n let allNested = uiConfig.getNestedConfigurators();\r\n\r\n let sceneNode = uiConfig.$sceneNode as kb3d.SceneNode;\r\n if (sceneNode) {\r\n for (var i = sceneNode.scenes.length - 1; i >= 0; i--) {\r\n var ns = sceneNode.scenes[i];\r\n if (!allNested.some(n => n === ns._configurator)) {\r\n this.destroyNestedScene(sceneNode, ns);\r\n }\r\n }\r\n }\r\n }\r\n\r\n protected destroyNestedScene(parentScene: kb3d.SceneNode, nestedScene: kb3d.SceneNode) {\r\n let nestedConfig = nestedScene._configurator as Configurator;\r\n if (nestedConfig) nestedConfig.$sceneNode = undefined;\r\n nestedScene._configurator = undefined;\r\n parentScene.scenes.remove(nestedScene);\r\n nestedScene._manager.dispose(); //dispose of the nested scene manager\r\n }\r\n\r\n public clearHandlers() {}\r\n\r\n public runAction(actionName: string): ng.IPromise> {\r\n let args = this.getRuleArgs(eRuleType.action);\r\n return this.runActionRule(actionName, args);\r\n }\r\n\r\n public runSceneFunction(args: IKb3dCallSceneFunctionArgs, config: Configurator) {\r\n let ruleArgs = null;\r\n if (config && config.$sceneConfigurator) {\r\n ruleArgs = this.getNestedSceneRuleArgs(\r\n config,\r\n config.$sceneConfigurator,\r\n eRuleType.function\r\n ) as Kb3dSceneFunctionRuleArgs;\r\n } else {\r\n ruleArgs = this.getRuleArgs(eRuleType.function) as Kb3dSceneFunctionRuleArgs;\r\n }\r\n ruleArgs.parameters = {};\r\n for (let p in args.parameters) {\r\n ruleArgs.parameters[p.toCamelCase()] = args.parameters[p];\r\n }\r\n\r\n let fn = null;\r\n if (config && config.$sceneConfigurator) {\r\n fn = config.$sceneConfigurator.functions.find(a => a.name.isEqual(args.name));\r\n }\r\n\r\n if (!fn) {\r\n fn = this.sceneConfig.functions.find(a => a.name.isEqual(args.name));\r\n }\r\n\r\n if (fn) {\r\n return this.ruleService.runRuleContainerAsync(fn, ruleArgs).then(r => {\r\n this.handleRuleError(fn.name + ' ' + fn.$type, r);\r\n return r;\r\n });\r\n } else {\r\n throw `Cannot find scene function with name ${args.name}`;\r\n }\r\n }\r\n\r\n public runFieldAction(elem: UiObject) {\r\n let args = this.getRuleArgs(eRuleType.field);\r\n return this.ruleService.runRuleContainerAsync(elem, args).then(res => {\r\n this.handleRuleError(elem.name + ' ' + elem.$type, res);\r\n return res;\r\n });\r\n }\r\n\r\n public onSceneClick(p: IKb3dPointerArgs) {\r\n this.clearHotspots();\r\n this.$scope.$digest();\r\n }\r\n\r\n public onKeyboard(k: IKeyboardArgs) {\r\n let args = this.getRuleArgs(eRuleType.action);\r\n args['keyArgs'] = k;\r\n\r\n return this.ruleService\r\n .runRuleTypeAsync(this.sceneConfig, eRuleType.keyboard, args as ISceneRuleArgs)\r\n .then(r => {\r\n this.handleRuleError(eRuleType.keyboard, r);\r\n this.$scope.$digest();\r\n });\r\n }\r\n\r\n public importUploadFieldImage(uiConfig: Configurator, field: Field, file?: File): ng.IPromise {\r\n return undefined;\r\n }\r\n\r\n public show() {\r\n super.show();\r\n this.viewer.startRender();\r\n }\r\n\r\n public hide() {\r\n this.viewer.stopRender();\r\n super.hide();\r\n }\r\n\r\n public resize() {}\r\n\r\n public snapshot(args: kb3d.ISnapshotArgs) {\r\n if (args['camera'] && !args.viewpoint) args.viewpoint = args['camera']; //backwards compatibility for old snapshot\r\n return this.viewer.snapshot.take(args);\r\n }\r\n\r\n protected toggleAr() {\r\n let rulesFn = (rt: eRuleType) => {\r\n return this.runRuleTypeAsync(this.sceneConfig, rt, this.getRuleArgs(rt)).then(() => {\r\n return this.runRules(false);\r\n });\r\n };\r\n\r\n if (this.arLoading.active()) {\r\n return;\r\n }\r\n\r\n let ruleType = this.$scope.arActive() ? eRuleType.xrExit : eRuleType.xrEnter;\r\n if (ruleType == eRuleType.xrEnter) {\r\n let subscription = this.viewer.ar.onSessionEnd.subscribe(() => {\r\n subscription.unsubscribe();\r\n return rulesFn(eRuleType.xrExit);\r\n });\r\n let overlayElem = document.querySelector('.xr-overlay') as HTMLElement | null;\r\n const arPromise = this.viewer.ar\r\n .start(overlayElem, () => rulesFn(eRuleType.xrEnter))\r\n .catch(err => {\r\n if (this.cArgs.dialogService) {\r\n this.$scope.$apply(() => {\r\n this.cArgs.dialogService.alert({\r\n type: eAlertType.error,\r\n msg: 'Could not enter AR: ' + err,\r\n persist: true,\r\n });\r\n });\r\n } else {\r\n console.warn('No Dialog Service!');\r\n console.error(err);\r\n }\r\n });\r\n this.arLoading.addPromise(arPromise);\r\n return arPromise;\r\n } else {\r\n return this.viewer.ar.end();\r\n }\r\n }\r\n\r\n protected updateHotspots(digest = true) {\r\n let hotspotProcessed = false;\r\n for (let hotspot of this.$scope.allHotspots) {\r\n const sceneNode = hotspot.$parentConfigurator?.$uiConfigurator?.$sceneNode as kb3d.SceneNode;\r\n if (sceneNode) {\r\n let sceneManager = sceneNode._manager;\r\n if (sceneManager) {\r\n if (hotspot.target && hotspot.targetNode && hotspot.visible) {\r\n hotspotProcessed = true;\r\n let targetNode = sceneManager.getById(hotspot.targetNode);\r\n if (targetNode) {\r\n let pos = this.viewer.camera.getScreenBoundingBoxOfNode(targetNode);\r\n if (pos) {\r\n this.positionHotspot(pos, hotspot);\r\n }\r\n }\r\n }\r\n if (hotspot.targetShape == eHotspotShape.mesh && hotspot.targetNode) {\r\n let eventTag = `hotspot_${hotspot.id}`;\r\n let node = sceneManager.getById(hotspot.targetNode);\r\n if (node) {\r\n if (hotspot.visible) {\r\n if (!sceneManager.clickHandlers.has(node, eventTag)) {\r\n sceneManager.clickHandlers.add(node, eventTag, () =>\r\n this.hotspotClick({} as any, hotspot)\r\n );\r\n }\r\n } else {\r\n //remove the click handler if the hotspot is invisible\r\n sceneManager.clickHandlers.delete(node, eventTag);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n // call digest manually on this scope instead of scope.$apply because $apply starts\r\n // at the root and digests everything.We only want to affect the hotspots here.\r\n if (hotspotProcessed && digest) {\r\n //this can be expensive, so only run if there is something to update\r\n this.$scope.$digest();\r\n }\r\n }\r\n\r\n protected clearHotspots() {\r\n for (let hotspot of this.$scope.allHotspots) {\r\n if (hotspot.target && hotspot.allowClose) {\r\n hotspot.open = false;\r\n }\r\n }\r\n }\r\n\r\n private hotspotCounter: number = 0;\r\n protected hotspotClick($event: ng.IAngularEvent, hotspot: Hotspot) {\r\n this.clearHotspots();\r\n hotspot.open = true;\r\n this.hotspotCounter++;\r\n hotspot.$zindex = this.hotspotCounter;\r\n\r\n let hSceneNode = hotspot.$parentConfigurator.$uiConfigurator.$sceneNode as kb3d.SceneNode;\r\n let handlers = hSceneNode._manager.hotspotClickHandlers.getByKey(hotspot);\r\n\r\n if (hotspot.idCamera) {\r\n let viewpoint = hSceneNode._manager.getById(hotspot.idCamera);\r\n if (viewpoint) {\r\n this.viewer.camera.animateToViewpoint(viewpoint, {\r\n duration: hotspot.animationDuration,\r\n });\r\n }\r\n }\r\n\r\n for (let handler of handlers) {\r\n let clickArgs: IHotspotClickArgs = { propagate: false };\r\n handler(clickArgs);\r\n }\r\n\r\n // some hotspot popups start off the screen because the height can't be calculated until it's shown\r\n // so we need to offload to recalculate the hotspot position after the digest\r\n this.$timeout(() => {\r\n if (hotspot.target && hotspot.targetNode && hotspot.visible) {\r\n let targetNode = hSceneNode._manager.getById(hotspot.targetNode);\r\n if (targetNode) {\r\n let pos = this.viewer.camera.getScreenBoundingBoxOfNode(targetNode);\r\n if (pos) {\r\n this.positionHotspot(pos, hotspot);\r\n }\r\n }\r\n }\r\n });\r\n }\r\n\r\n protected hotspotCloseClick($event: ng.IAngularEvent, hotspot: Hotspot) {\r\n $event.stopPropagation();\r\n hotspot.open = false;\r\n }\r\n\r\n public getRuleArgs(ruleType: eRuleType): Kb3dSceneRuleArgs {\r\n let args: Kb3dSceneRuleArgs;\r\n if (ruleType == eRuleType.function) {\r\n args = new Kb3dSceneFunctionRuleArgs(this);\r\n } else {\r\n args = new Kb3dSceneRuleArgs(this);\r\n }\r\n args.environment = this.environment;\r\n args.baseUrl = this.baseUrl;\r\n args.configurator = this.sceneConfig.idProduct ? this.uiConfig : this.sceneConfig;\r\n args.kom = args.configurator.$manager;\r\n args.parentKom = args.configurator.$parentConfigurator ? args.configurator.$parentConfigurator.$manager : null;\r\n args.sceneKom = this.sceneConfig.$manager;\r\n args.sceneNode = this.sceneNode;\r\n //args.sceneApi = this.sceneApi;\r\n args.isRender = this.isRender;\r\n args.renderPass = this.renderPass;\r\n //args.sceneUtils = this.sceneService.getSceneUtilities(this.sceneApi, ruleType);\r\n args.clientLanguage = this.clientLanguage;\r\n args.ruleType = ruleType;\r\n args.xrActive = this.viewer.ar.xrActive;\r\n\r\n return args;\r\n }\r\n\r\n public getNestedSceneRuleArgs(uiConfig: Configurator, sceneConfig: Configurator, ruleType: eRuleType) {\r\n let args = new Kb3dSceneRuleArgs(this);\r\n args.environment = this.environment;\r\n args.baseUrl = this.baseUrl;\r\n args.configurator = uiConfig;\r\n args.kom = args.configurator.$manager;\r\n args.parentKom = args.configurator.$parentConfigurator ? args.configurator.$parentConfigurator.$manager : null;\r\n args.sceneKom = sceneConfig.$manager;\r\n args.sceneNode = uiConfig.$sceneNode;\r\n //args.sceneApi = this.sceneApi;\r\n args.isRender = this.isRender;\r\n args.renderPass = this.renderPass;\r\n //args.sceneUtils = this.sceneService.getSceneUtilities(this.sceneApi, ruleType);\r\n args.clientLanguage = this.clientLanguage;\r\n args.ruleType = ruleType;\r\n args.xrActive = this.viewer.ar.xrActive;\r\n\r\n return args;\r\n }\r\n}\r\n\r\nexport class Kb3dSceneRuleArgs implements ISceneRuleArgs {\r\n constructor(public kbv: Kb3dViewer) {\r\n this.isMobile = kbv.isMobile;\r\n }\r\n public environment: eEnvironment;\r\n public baseUrl: string;\r\n public configurator: Configurator;\r\n public kom: KbObjectManager;\r\n public parentKom: KbObjectManager;\r\n public sceneKom: KbObjectManager;\r\n public sceneNode: kb3d.SceneNode;\r\n public ruleType: eRuleType;\r\n public isRender: boolean;\r\n public renderPass: string;\r\n public isMobile: boolean;\r\n public xrActive: boolean;\r\n public clientLanguage: string;\r\n public logs: ClientLogger = new ClientLogger();\r\n public upload() {\r\n //return this.viewer.upload();\r\n }\r\n\r\n public sendMessage(msg: IMessage) {\r\n this.kbv.sendMessage(msg);\r\n }\r\n public selectPage(page) {\r\n if (this.kbv.navigateToElement) {\r\n this.kbv.navigateToElement(page);\r\n }\r\n }\r\n public convertCurrency(obj) {\r\n return null;\r\n }\r\n public getTables(args: IGetTableRuleArgs) {\r\n return new KPromise(args.ids.map(tid => this.kbv.tableArraysDb[tid]));\r\n }\r\n\r\n public getById(id: string) {\r\n return this.sceneNode._manager.getById(id);\r\n }\r\n\r\n public getByName(name: string) {\r\n const node = this.sceneNode._manager.getFirstNodeByName(name, true);\r\n if (!node) {\r\n console.warn(`No nodes \"${name}\" found`);\r\n }\r\n }\r\n\r\n public getIdByName(name: string) {\r\n let node = this.sceneNode._manager.getNodeByIdOrName(name);\r\n if (!node) {\r\n console.warn(`No nodes \"${name}\" found`);\r\n } else {\r\n return node.id;\r\n }\r\n }\r\n\r\n public getParent(n: string | kb3d.Kb3dObject) {\r\n let node = this.sceneNode._manager.getNodeByIdOrName(n);\r\n if (node) {\r\n return node._parent;\r\n }\r\n }\r\n\r\n public getNestedPathTo(node: kb3d.Kb3dObject) {\r\n return this.sceneNode.getNestedPathTo(node);\r\n }\r\n\r\n public getNestedPathInConfigurator(...configs: (Configurator | string)[]) {\r\n let m = this.sceneNode._manager;\r\n\r\n const lastItem = configs.pop(); // Last item can be a node ID or name as well\r\n let path = configs.reduce((result, config) => {\r\n if (typeof config === 'string') {\r\n result += config;\r\n const configurator = this.kom.getByName(config);\r\n if (configurator instanceof Configurator && configurator.$sceneNode) {\r\n m = configurator.$sceneNode._manager;\r\n }\r\n } else {\r\n result += config.name;\r\n if (config.$sceneNode) {\r\n m = config.$sceneNode._manager;\r\n }\r\n }\r\n\r\n return result + '/';\r\n }, '');\r\n\r\n if (typeof lastItem === 'string') {\r\n const lastConfig = this.kom.getByName(lastItem, false);\r\n if (lastConfig instanceof Configurator) {\r\n if (!lastConfig.$sceneNode) {\r\n console.warn('No Scene on configurator ' + lastConfig.name);\r\n return null;\r\n }\r\n path += lastConfig.name + '/' + lastConfig.$sceneNode.id;\r\n } else {\r\n const kb3dNode = m.getFirstNodeByName(lastItem);\r\n if (kb3dNode) {\r\n path += kb3dNode.id;\r\n } else {\r\n path += lastItem;\r\n }\r\n }\r\n } else {\r\n const lastConfig = lastItem;\r\n if (!lastConfig.$sceneNode) {\r\n console.warn('No Scene on configurator ' + lastConfig.name);\r\n return null;\r\n }\r\n path += lastConfig.name + '/' + lastConfig.$sceneNode.id;\r\n }\r\n\r\n return '@' + path;\r\n }\r\n\r\n public setParent(opts: ISetParentArgs) {\r\n const manager = this.sceneNode._manager;\r\n const item = manager.getNodeByIdOrName(opts.node) as Kb3dObject;\r\n const newParentNode = opts.newParent ? manager.getNodeByIdOrName(opts.newParent, false) : undefined;\r\n const transform =\r\n opts.preservePosition && isSpaceNode(item)\r\n ? this.kbv.viewer.getTransformSpaceDifference(item, newParentNode)\r\n : undefined;\r\n\r\n let clickHandlers: Record | undefined;\r\n let doubleClickHandlers: Record | undefined;\r\n let draggables: Record | undefined;\r\n\r\n if (item._parent) {\r\n if (isSpaceNode(item) || isAnnotation(item)) {\r\n clickHandlers = manager.clickHandlers.deleteByKey(item);\r\n doubleClickHandlers = manager.doubleClickHandlers.deleteByKey(item);\r\n draggables = manager.draggables.deleteByKey(item);\r\n }\r\n\r\n item._parent.removeChildren(item);\r\n }\r\n\r\n return this.kbv.viewer.forceAndWaitForNextRender().then(() => {\r\n if (transform && isSpaceNode(item)) {\r\n item.setRotationQuaternion(transform.rotationQuaternion);\r\n item.scaling = transform.scale;\r\n item.position = transform.translation;\r\n }\r\n newParentNode.addChildren(item);\r\n item.calculateParents();\r\n\r\n if (isSpaceNode(item) || isAnnotation(item)) {\r\n if (clickHandlers) {\r\n for (const tag in clickHandlers) {\r\n for (const handler of clickHandlers[tag]) {\r\n manager.clickHandlers.add(item, tag, handler);\r\n }\r\n }\r\n }\r\n if (doubleClickHandlers) {\r\n for (const tag in doubleClickHandlers) {\r\n for (const handler of doubleClickHandlers[tag]) {\r\n manager.doubleClickHandlers.add(item, tag, handler);\r\n }\r\n }\r\n }\r\n if (draggables) {\r\n for (const tag in draggables) {\r\n for (const handler of draggables[tag]) {\r\n manager.draggables.add(item, tag, handler);\r\n }\r\n }\r\n }\r\n }\r\n });\r\n\r\n // const newNode = this.clone({ node: item, parent: newParentNode });\r\n }\r\n\r\n public setProperty(args: IKb3dSetPropertyArgs) {\r\n let m = this.sceneNode._manager;\r\n let nodes = new Array();\r\n let id = args.id as any;\r\n if (args.nested) {\r\n nodes.push(this.getNestedSceneNode(args.nested));\r\n } else if (id && (id instanceof kb3d.Kb3dObject || id === this.kbv.viewer.camera.activeCamera)) {\r\n nodes.push(id);\r\n } else {\r\n nodes = m.getNodesByIdOrName(args.id, true);\r\n }\r\n\r\n if (nodes.length === 0) {\r\n console.warn(`No nodes \"${args.id}\" found`);\r\n }\r\n\r\n if (args.feature) {\r\n nodes = nodes.selectMany(n => {\r\n return n instanceof MaterialNode\r\n ? n.getTextureByName(args.feature)\r\n : n instanceof SpaceNode\r\n ? n.getFeatureByName(args.feature)\r\n : null;\r\n });\r\n }\r\n\r\n for (let node of nodes) {\r\n if (args.subProp && !kb3d.Token.withKey(args.propType as any).isPrimitive()) {\r\n //cover the case of TextureNodes inside a material\r\n node[args.prop][args.subProp] = args.value;\r\n } else {\r\n let val = this.normalizePropValue(node, args);\r\n node[args.prop] = val;\r\n }\r\n }\r\n }\r\n\r\n public getProperty(args: IKb3dGetPropertyArgs) {\r\n let m = this.sceneNode._manager;\r\n let id = args.id as any;\r\n let node: Kb3dObject;\r\n if (id && (id instanceof kb3d.Kb3dObject || id === this.kbv.viewer.camera.activeCamera)) {\r\n node = id;\r\n } else {\r\n node = m.getNodeByIdOrName(args.id, true);\r\n }\r\n\r\n if (args.feature && node instanceof MaterialNode) {\r\n node = node.getTextureByName(args.feature);\r\n }\r\n\r\n if (args.feature && node instanceof SpaceNode) {\r\n node = node.getFeatureByName(args.feature);\r\n }\r\n\r\n if (node) {\r\n let val = args.prop ? node[args.prop] : node;\r\n if (args.prop && args.subProp) val = val[args.subProp];\r\n return val;\r\n } else {\r\n console.warn(`No nodes \"${args.id}\" found`);\r\n }\r\n }\r\n\r\n protected normalizePropValue(node: kb3d.Kb3dObject, args: IKb3dSetPropertyArgs): any {\r\n if (!args.subProp && args.value == null) {\r\n return null; // Return null as-is if applying directly to the prop\r\n }\r\n if (!args.subProp && args.propType && args.propType.isEqual(kb3d.Token.KbColor.key)) {\r\n return this.convertColor(args.value, eColorFormat.kbcolor);\r\n }\r\n if (args.subProp) {\r\n if (kb3d.Token.withKey(args.propType as any).isPrimitive()) {\r\n if (args.value == null) {\r\n throw Error(`Cannot set component of ${args.propType} to null (on ${node.name}/${args.prop})`);\r\n }\r\n let currentVal = node[args.prop];\r\n let newVal = { ...currentVal, [args.subProp]: args.value };\r\n return this.sceneNode._manager.create(kb3d.Token.withKey(args.propType as any), newVal);\r\n } /**else { //it's not a primitive but has a sub property\r\n node[args.prop][args.subProp] = args.value;\r\n return node[args.prop];\r\n }*/\r\n }\r\n\r\n return args.value;\r\n }\r\n\r\n protected getNestedSceneNode(nestedNameOrInstance: string | Configurator): kb3d.SceneNode {\r\n let nestedConfig: Configurator;\r\n if (typeof nestedNameOrInstance === 'string' || nestedNameOrInstance instanceof String) {\r\n //if it's a string find the nested configurator\r\n nestedConfig = this.configurator.$manager.getByName(nestedNameOrInstance as string);\r\n } else if (nestedNameOrInstance instanceof Configurator) {\r\n nestedConfig = nestedNameOrInstance;\r\n }\r\n\r\n if (!nestedConfig) {\r\n throw Error(`could not find nested configurator with name '${nestedNameOrInstance}'`);\r\n }\r\n\r\n return nestedConfig.$sceneNode;\r\n }\r\n\r\n public convertColor(from: any, toFormat: eColorFormat = eColorFormat.kbcolor) {\r\n if (toFormat == eColorFormat.kbcolor && from instanceof kb3d.KbColor) {\r\n return from;\r\n }\r\n\r\n if (from instanceof kb3d.KbColor) {\r\n from = from.toIntObject();\r\n }\r\n\r\n let color = new Color(from);\r\n let result: any;\r\n if (toFormat == eColorFormat.hex) {\r\n result = color.toHexString();\r\n } else if (toFormat == eColorFormat.hsl) {\r\n result = color.toHsl();\r\n } else if (toFormat == eColorFormat.hslString) {\r\n result = color.toHslString();\r\n } else if (toFormat == eColorFormat.hsv) {\r\n result = color.toHsv();\r\n } else if (toFormat == eColorFormat.hsvString) {\r\n result = color.toHsvString();\r\n } else if (toFormat == eColorFormat.rgb) {\r\n result = color.toRgb();\r\n } else if (toFormat == eColorFormat.rgbString) {\r\n result = color.toRgbString();\r\n } else if (toFormat == eColorFormat.kbcolor) {\r\n let rgb = color.toRgb();\r\n result = kb3d.KbColor.FromIntObject(rgb);\r\n }\r\n\r\n return result;\r\n }\r\n\r\n public colorOperation(args: IColorOperationArgs) {\r\n if (args.color instanceof KbColor) {\r\n args.color = args.color.toIntObject();\r\n }\r\n\r\n let color = new Color(args.color);\r\n color = color[args.operation](args.amount);\r\n\r\n return KbColor.FromIntObject(color.toRgb());\r\n }\r\n\r\n public addClickHandler(args: IKb3dAddClickHandlerArgs) {\r\n args.handler = this.digestEvent(args.handler); //the viewer runs the event, so we need to wrap it for the angular digest\r\n this.sceneNode._manager.clickHandlers.add(args.id, this.getHandlerTag(args.tag), args.handler);\r\n }\r\n\r\n public addDoubleClickHandler(args: IKb3dAddClickHandlerArgs) {\r\n args.handler = this.digestEvent(args.handler); //the viewer runs the event, so we need to wrap it for the angular digest\r\n this.sceneNode._manager.doubleClickHandlers.add(args.id, this.getHandlerTag(args.tag), args.handler);\r\n }\r\n\r\n public addDraggable(args: kb3d.IDraggable & { tag?: string }) {\r\n this.sceneNode._manager.draggables.add(args.id, this.getHandlerTag(args.tag), args);\r\n }\r\n\r\n public addHotspotClickHandler(args: IKb3dAddHotspotClickHandlerArgs) {\r\n //no $digest wrap needed for hotspot handler because the event is already coming from angular\r\n this.sceneNode._manager.hotspotClickHandlers.set(args.hotspot, this.getHandlerTag(args.tag), args.handler);\r\n }\r\n\r\n public addBoundboxChangeHandler(args: IKb3dAdBoundingboxWatcherArgs) {\r\n args.handler = this.digestEvent(args.handler); //the viewer runs the event, so we need to wrap it for the angular digest\r\n this.sceneNode._manager.boundingboxChangeHandlers.add(args.id, this.getHandlerTag(args.tag), {\r\n handler: args.handler,\r\n mode: args.mode,\r\n });\r\n }\r\n\r\n protected getHandlerTag(argsTag: string) {\r\n if (this.ruleType == eRuleType.scene) {\r\n //scene rule handlers get a tag of 'scene' automatically and are removed automatically\r\n return eRuleType.scene;\r\n } else {\r\n //those added by other rules get the tag given by the snap user\r\n return argsTag;\r\n }\r\n }\r\n\r\n public clearHandlers(args: IKb3dClearHandlerArgs) {\r\n let handlerMap: kb3d.TagArrayMap;\r\n let m = this.sceneNode._manager;\r\n if (args.handlerType == kb3d.eHandler.click) {\r\n handlerMap = m.clickHandlers;\r\n } else if (args.handlerType == kb3d.eHandler.doubleClick) {\r\n handlerMap = m.doubleClickHandlers;\r\n } else if (args.handlerType == kb3d.eHandler.draggable) {\r\n handlerMap = m.draggables;\r\n } else if (args.handlerType == kb3d.eHandler.hotspot) {\r\n handlerMap = m.hotspotClickHandlers;\r\n }\r\n\r\n if (handlerMap) {\r\n if (args.tag) {\r\n handlerMap.deleteByTag(args.tag);\r\n } else {\r\n handlerMap.clear();\r\n }\r\n }\r\n }\r\n\r\n public animate(args: IKb3dAnimateArgs) {\r\n let nodes = new Array();\r\n if (args.node) {\r\n nodes = [args.node];\r\n } else {\r\n nodes = this.sceneNode._manager.getNodesByIdOrName(args.id, true);\r\n }\r\n let promises = new Array>();\r\n for (let node of nodes) {\r\n let toValue = this.normalizePropValue(node, args);\r\n let a = {\r\n ...args,\r\n toValue: toValue,\r\n node: node,\r\n } as kb3d.IAnimation;\r\n\r\n promises.push(this.kbv.viewer.animation.queue(a));\r\n }\r\n return Promise.all(promises);\r\n }\r\n\r\n public frameCamera(args: kb3d.IFramingOptions & { node: kb3d.SpaceNode }) {\r\n this.kbv.viewer.camera.frameCamera(args.node, args);\r\n }\r\n\r\n public animateCamera(args: kb3d.ICameraAnimationOptions & { viewpoint: kb3d.ViewpointNode }) {\r\n return this.kbv.viewer.camera.animateToViewpoint(args.viewpoint, args);\r\n }\r\n\r\n public create(args: IKb3dCreateNodeArgs): T {\r\n let token = kb3d.Token.withKey(args.type as any);\r\n let n = this.sceneNode._manager.create(token, args.args);\r\n this.addToParent(n, args.parent, token);\r\n\r\n return n;\r\n }\r\n\r\n public createSketchPath(args: IKb3dCreateSketchPathArgs): kb3d.SketchPath {\r\n let n = this.sceneNode._manager.create(kb3d.Token.SketchPath, args.args);\r\n this.addToParent(n, args.parent, kb3d.Token.SketchPath);\r\n const controlPoints = args.controlPoints.filter(input => input && input instanceof kb3d.SketchControlPoint);\r\n n.addChildren(...controlPoints);\r\n\r\n return n;\r\n }\r\n\r\n public clone(args: IKb3dCloneNodeArgs): Kb3dObject {\r\n let o = args.node as Kb3dObject;\r\n let clone = this.sceneNode._manager!.clone(o);\r\n for (let p in args.args) {\r\n clone[p] = args.args[p];\r\n }\r\n let token = kb3d.Token.withKey(clone.$type);\r\n this.addToParent(clone, args.parent, token);\r\n\r\n return clone;\r\n }\r\n\r\n public delete(node: Kb3dObject) {\r\n if (node && node._parent) {\r\n node._parent.removeChildren(node);\r\n }\r\n }\r\n\r\n public getChildrenOfType(args: IKb3dGetChildrenOfTypeArgs): Array {\r\n let n = args.node;\r\n if (n instanceof kb3d.Kb3dObject) {\r\n let tok = kb3d.Token.withKey(args.type as any);\r\n return n.filterByType(tok);\r\n } else {\r\n return [];\r\n }\r\n }\r\n\r\n public searchByName(name: string) {\r\n return this.sceneNode._manager.getNodesByIdOrName(name, true);\r\n }\r\n\r\n public getActiveCamera() {\r\n return this.kbv.viewer.camera.activeCamera;\r\n }\r\n\r\n public highlight(args: IKb3dHighlightArgs) {\r\n this.kbv.viewer.forceAndWaitForNextRender().then(() => {\r\n //wait for next render to make sure the mesh exists before highlighting\r\n let nodes = this.sceneNode._manager.getNodesByIdOrName(args.id);\r\n for (let n of nodes) {\r\n if (n instanceof kb3d.SpaceNode) {\r\n if (args.on) {\r\n this.kbv.viewer.highlighter.add(n, this.convertColor(args.color, eColorFormat.kbcolor));\r\n } else {\r\n this.kbv.viewer.highlighter.remove(n);\r\n }\r\n }\r\n }\r\n });\r\n }\r\n\r\n public clearHighlights() {\r\n this.kbv.viewer.highlighter.clearAll();\r\n }\r\n\r\n public activateGizmo(args: IKb3dActivateGizmoArgs) {\r\n let attachMesh: kb3d.SpaceNode;\r\n // Rotation with override space node doesn't function well. Disable that functionality so people don't try to use it,\r\n // Until we can swap axis/angle gizmo in and fix the transform space conversion\r\n if (args.gizmo === 'rotate') {\r\n delete args.overrideSpaceNode;\r\n }\r\n if (args.overrideSpaceNode) {\r\n attachMesh = args.overrideSpaceNode;\r\n } else {\r\n attachMesh = args.node;\r\n }\r\n const mesh = args.node as kb3d.SpaceNode;\r\n this.kbv.viewer.gizmos.clearGizmo();\r\n if (args.gizmo === 'rotate') {\r\n const updates = this.kbv.viewer.gizmos.rotate([attachMesh], undefined, undefined, args.axisVisibility);\r\n let startQ = KbQuaternion.FromRotationAxis(mesh.rotationAxis, mesh.rotationAngle);\r\n let startEuler = mesh.eulerRotation.clone();\r\n updates.update.subscribe(updates => {\r\n mesh._primeMover = true;\r\n updates.forEach((update, index) => {\r\n mesh.position = mesh.position.add(update.position);\r\n let qGizmo: KbQuaternion = KbQuaternion.FromYawPitchRoll(update.rotation);\r\n\r\n if (!args.overrideSpaceNode) {\r\n if (mesh.useEuler) {\r\n mesh.eulerRotation = mesh.eulerRotation.add(update.rotation);\r\n } else {\r\n const q = KbQuaternion.FromRotationAxis(mesh.rotationAxis, mesh.rotationAngle);\r\n const z = KbQuaternion.FromYawPitchRoll(update.rotation);\r\n const result = q.multiply(z);\r\n mesh.rotationAngle = result.getAngle();\r\n mesh.rotationAxis = result.getAxis();\r\n }\r\n return;\r\n } else {\r\n const bnode = this.kbv.viewer.getRendererNode(args.node as SpaceNode);\r\n if (bnode) {\r\n const inSpace = bnode.parent ? bnode.parent.computeWorldMatrix(true) : undefined;\r\n const transform = applyTransformToSpace(update.worldTransformMatrix, inSpace);\r\n qGizmo = transform.rotation;\r\n }\r\n\r\n if (mesh.useEuler) {\r\n mesh.eulerRotation = startEuler.add(qGizmo.toEuler());\r\n } else {\r\n const result = startQ.multiply(qGizmo);\r\n mesh.rotationAngle = result.getAngle();\r\n mesh.rotationAxis = result.getAxis();\r\n }\r\n }\r\n });\r\n });\r\n\r\n updates.totalDelta.subscribe(() => {\r\n startQ = KbQuaternion.FromRotationAxis(mesh.rotationAxis, mesh.rotationAngle);\r\n startEuler = mesh.eulerRotation.clone();\r\n if (args.dropped) {\r\n args.dropped();\r\n }\r\n mesh._primeMover = false;\r\n });\r\n } else if (args.gizmo === 'position') {\r\n //update attachMesh \r\n let updates = null\r\n if (args.overrideSpaceNode && args.overrideSpaceNode instanceof SpaceNode) {\r\n const rotationQuaternion = args.overrideSpaceNode.getRotationQuaternion();\r\n updates = this.kbv.viewer.gizmos.position(args.node, undefined, args.axisVisibility, rotationQuaternion.toQuat());\r\n } else {\r\n updates = this.kbv.viewer.gizmos.position(attachMesh, undefined, args.axisVisibility);\r\n }\r\n if (updates) {\r\n updates.update.subscribe(newPosition => {\r\n mesh._primeMover = true;\r\n mesh.position = mesh.position.add(newPosition);\r\n });\r\n }\r\n\r\n if (args.dropped) {\r\n updates.totalDelta.subscribe(() => {\r\n args.dropped();\r\n mesh._primeMover = false;\r\n });\r\n }\r\n }\r\n\r\n function convertSpace(gizmoSpace: TransformNode | undefined, nodeSpace: TransformNode | undefined) {}\r\n }\r\n\r\n public clearGizmos() {\r\n this.kbv.viewer.gizmos.clearGizmo();\r\n }\r\n\r\n public activateSketchEditor(args: IKb3dActivateSketchArgs) {\r\n this.clearSketchEditor();\r\n if (args.node instanceof kb3d.SketchNode) {\r\n this.kbv.viewer.sketchEditor.startOnPlane(\r\n args.node,\r\n {\r\n normal: (args.axis as kb3d.eAxis) || args.node.normal,\r\n intersect: args.intersect || args.node.position,\r\n },\r\n {\r\n snapSize: args.snapSize || undefined,\r\n }\r\n );\r\n if (args.modified) {\r\n this.kbv.viewer.sketchEditor.mouseUp.subscribe(() => {\r\n this.kbv.viewer.forceAndWaitForNextRender().then(() => {\r\n args.modified();\r\n });\r\n });\r\n }\r\n }\r\n }\r\n\r\n public clearSketchEditor() {\r\n this.kbv.viewer.sketchEditor.clear();\r\n }\r\n\r\n public overwriteSketchWithSVG(args) {\r\n if (args.svgImage) {\r\n fetch(args.svgImage)\r\n .then(resp => resp.blob())\r\n .then(blob => this.kbv.viewer.applySvgToSketch(args.node, blob))\r\n .catch(e => {\r\n console.warn('Could not fetch image ' + args.svgImage, e);\r\n });\r\n }\r\n }\r\n\r\n public getAbsolutePosition(node: string | kb3d.SpaceNode | kb3d.Connector) {\r\n let n = this.sceneNode._manager.getNodeByIdOrName(node);\r\n if (n) {\r\n let bnode = this.kbv.viewer.getRendererNode(n as SpaceNode);\r\n if (bnode) {\r\n return kb3d.KbVector.From(bnode.getAbsolutePosition());\r\n }\r\n }\r\n return kb3d.KbVector.Zero();\r\n }\r\n\r\n public getSketchPathLength(path: kb3d.SketchPath) {\r\n const pointsArray: [number, number, number][] = [];\r\n path._points.forEach(point => {\r\n pointsArray.push([point.x, point.y, point.z]);\r\n });\r\n\r\n return computeLength(pointsArray);\r\n\r\n function computeLength(path: number[][]): number {\r\n let l = 0;\r\n for (let i = 1; i < path.length; i++) {\r\n const point = path[i];\r\n const prevPoint = path[i - 1];\r\n l += Math.hypot(...[point[0] - prevPoint[0], point[1] - prevPoint[1], point[2] - prevPoint[2]]);\r\n }\r\n return l;\r\n }\r\n }\r\n\r\n public getBoundingBox(node: kb3d.SpaceNode, space: 'world' | 'local' = 'world') {\r\n if (space === 'world') {\r\n return this.kbv.viewer.bbCache.getWorld(node);\r\n } else {\r\n return this.kbv.viewer.bbCache.refreshAndGet(node);\r\n }\r\n }\r\n\r\n public nodesIntersect(node1: kb3d.SpaceNode, node2: kb3d.SpaceNode) {\r\n return this.kbv.viewer.nodesIntersect(node1, node2);\r\n }\r\n\r\n public copyPropertiesTo(fromNode: kb3d.Kb3dObject, toNode: kb3d.Kb3dObject) {\r\n if (this.sceneNode && this.sceneNode._manager) {\r\n this.sceneNode._manager.assign(toNode, fromNode, { copyingToDifferentNode: true });\r\n }\r\n }\r\n\r\n public getMateChain(node: kb3d.SpaceNode) {\r\n const activeMates = this.kbv.viewer.getActiveMates();\r\n return [node, ...Array.from(kb3d.getNodeChain(node, activeMates))];\r\n }\r\n\r\n public rotate(args: { node: kb3d.SpaceNode; axis: kb3d.KbVector; angle: number }) {\r\n args.node.rotate(args.axis, args.angle);\r\n }\r\n\r\n public callSceneFunction(args: IKb3dCallSceneFunctionArgs, config: Configurator) {\r\n if (!this.kbv) {\r\n console.warn(`Scene function ${args.name} was called but a scene is not loaded.`);\r\n return Promise.reject();\r\n }\r\n return this.kbv.runSceneFunction(args, config).then(r => r.parameters.returnValue);\r\n }\r\n\r\n public waitForNextRender() {\r\n return this.kbv.viewer.forceAndWaitForNextRender();\r\n }\r\n\r\n public convertAxisAngleToEuler(axis: kb3d.KbVector, angle: number) {\r\n const q = kb3d.KbQuaternion.FromRotationAxis(axis, angle);\r\n return q.toEuler().round(0.0000001); //round out floating point errors\r\n }\r\n\r\n public getGlobalMaterialNode(id: string) {\r\n return new Promise((resolve, reject) =>\r\n this.kbv.viewer.rendererManager.material\r\n .loadGlobalMaterial(id, this.sceneNode._manager!.services)\r\n .subscribe(resolve, reject)\r\n );\r\n }\r\n\r\n protected addToParent(node: Kb3dObject, parent: Kb3dObject, childToken: kb3d.Token) {\r\n if (parent) {\r\n parent.addChildren(node);\r\n }\r\n }\r\n\r\n protected digestEvent(ev: (a: any) => void) {\r\n return a => {\r\n ev(a);\r\n this.kbv.$scope.$digest();\r\n };\r\n }\r\n}\r\n\r\nexport class Kb3dSceneFunctionRuleArgs extends Kb3dSceneRuleArgs {\r\n constructor(public kbv: Kb3dViewer) {\r\n super(kbv);\r\n }\r\n public parameters: any;\r\n public returnValue: any;\r\n}\r\n","import { NgInterceptor } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { eEnvironment, IRootScope } from \"@models\";\r\nimport { Utils } from \"@tools\";\r\n\r\n@NgInterceptor({\r\n token: Token.CacheBusterInterceptor,\r\n dependencies: [\r\n Token.$Injector,\r\n Token.$RootScope,\r\n Token.$TemplateCache,\r\n Token.$Q,\r\n ]\r\n})\r\nexport class CacheBusterInterceptor {\r\n constructor(\r\n private $injector: ng.auto.IInjectorService,\r\n private $rootScope: IRootScope,\r\n private $templateCache: ng.ITemplateCacheService,\r\n private $q: ng.IQService\r\n ) {\r\n\r\n return {\r\n request: (config: ng.IRequestConfig) => {\r\n // if it's already in the templatecache, then just get it from there\r\n if ($templateCache.get(config.url)) {\r\n return config;\r\n }\r\n\r\n if (config.method == \"GET\") {\r\n // we only cache-bust stuff from our own server. Presumably these requests will have a relative url\r\n if (!Utils.isAbsoluteUrl(config.url)) {\r\n let extension = Utils.getExtension(config.url) || \"\";\r\n extension = extension.toLowerCase();\r\n\r\n // non file calls in the test and prod environments should send the last deploy,\r\n // which allows the browser cache to store results for some calls\r\n let company = this.$rootScope.company;\r\n let env = this.$rootScope.environment;\r\n if (env != eEnvironment.dev) {\r\n let lastDeploy = (env == eEnvironment.test ? company.lastTestDeployment : company.lastProdDeployment);\r\n if (!extension) {\r\n let prefix = \"?\";\r\n if (config.url.search(\"\\\\?\") !== -1) {\r\n prefix = \"&\";\r\n }\r\n config.url += `${prefix}d=${lastDeploy}&v=${$rootScope.cacheBuster}`;\r\n }\r\n }\r\n }\r\n }\r\n\r\n return config;\r\n }\r\n } as any;\r\n }\r\n}\r\n","import * as angular from \"angular\";\r\nimport { IRootScope } from \"@models\";\r\nimport { NgInterceptor } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\n@NgInterceptor({\r\n token: Token.ErrorInterceptor,\r\n dependencies: [\r\n Token.$Injector,\r\n Token.$RootScope,\r\n Token.$Q,\r\n ]\r\n})\r\nexport class ErrorInterceptor {\r\n constructor(\r\n private $injector: ng.auto.IInjectorService,\r\n private $rootScope: IRootScope,\r\n private $q: ng.IQService\r\n ) {\r\n\r\n return {\r\n response: response => {\r\n return response;\r\n },\r\n responseError: response => {\r\n let $http: ng.IHttpService = $injector.get(\"$http\");\r\n let config = response.config;\r\n if (!config.ignoreErrors) {\r\n switch (response.status) {\r\n case 400:\r\n case 401:\r\n case 0:\r\n break;\r\n\r\n default:\r\n let msg: string;\r\n msg = \"status: \" + response.status + \"\\n\";\r\n msg += \"data: \\n\" + angular.toJson(response.data);\r\n\r\n alert(msg);\r\n break;\r\n }\r\n }\r\n return $q.reject(response);\r\n }\r\n } as any;\r\n }\r\n}\r\n","import { NgInterceptor } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { SecurityRetryService } from \"@app/services/security-retry.service\";\r\nimport { IRootScope } from \"@models\";\r\nimport { events } from \"@tools\";\r\n\r\n\r\nexport class ForbiddenReason {\r\n public static SsoNoGroups: string = \"SsoNoGroups\";\r\n public static InsufficientPermissions: string = \"InsufficientPermissions\";\r\n}\r\n\r\n@NgInterceptor({\r\n token: Token.SecurityInterceptor,\r\n dependencies: [\r\n Token.$Injector,\r\n Token.SecurityRetryService,\r\n Token.$RootScope,\r\n Token.$Q,\r\n ]\r\n})\r\nexport class SecurityInterceptor {\r\n constructor(\r\n private $injector: ng.auto.IInjectorService,\r\n private securityRetryQueue: SecurityRetryService,\r\n private $rootScope: IRootScope,\r\n private $q: ng.IQService\r\n ) {\r\n\r\n return {\r\n request: (request: ng.IRequestConfig) => {\r\n if ($rootScope.isSfdcCpq) {\r\n request.headers[\"kb-context\"] = \"sfdccpq\"\r\n }\r\n return request;\r\n },\r\n response: (response: ng.IHttpPromiseCallbackArg) => {\r\n return response;\r\n },\r\n responseError: (response: ng.IHttpResponse) => {\r\n let config = (response.config) as any;\r\n if (!config.ignoreSecurity) {\r\n let $http: ng.IHttpService = $injector.get(\"$http\");\r\n let promise;\r\n if (response.status === 401) {\r\n // if a request set the config to ignore auth, then we don't add the item for replay\r\n if (!response.config.doNotReplay) {\r\n promise = securityRetryQueue.pushRetryFn(\"unauthorized-server\",\r\n () => $http(response.config));\r\n }\r\n\r\n $rootScope.user = null;\r\n $rootScope.$broadcast(events.loginRequested);\r\n if (promise) {\r\n return promise;\r\n }\r\n }\r\n if (response.status === 403) {\r\n if (response.data == ForbiddenReason.SsoNoGroups) {\r\n alert(\"We could not find proper permissions for this user. Please contact your system administrator for assistance.\");\r\n $rootScope.$broadcast(events.loginRequested);\r\n }\r\n else {\r\n $rootScope.$broadcast(events.permissionDenied);\r\n }\r\n }\r\n }\r\n return $q.reject(response);\r\n }\r\n } as any;\r\n }\r\n }\r\n","import { NgService } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport * as kb from \"@models\";\r\nimport { IEntity, IRootScope, meta } from \"@models\";\r\nimport { Utils } from \"@tools\";\r\n\r\nexport interface IProxyClient {\r\n getFromEnvironment(id: number, env: string, tracker?: ng.IPromiseTracker): ng.IPromise;\r\n rebuildIndex(): ng.IPromise;\r\n}\r\n\r\n@NgService({\r\n token: Token.ApiService,\r\n dependencies: [\r\n Token.$Http,\r\n Token.$Q,\r\n Token.$RootScope,\r\n Token.$Location\r\n ]\r\n})\r\nexport class ApiService {\r\n\r\n constructor(\r\n private $http: ng.IHttpService,\r\n private $q: ng.IQService,\r\n private $rootScope: IRootScope,\r\n private $location: ng.ILocationService\r\n ) {\r\n let queryString = $location.search();\r\n let cookieToken = queryString[\"cookieToken\"];\r\n if (cookieToken) {\r\n $http.defaults.headers.common[\"x-embed-token\"] = cookieToken;\r\n }\r\n }\r\n\r\n // public injection(): any[] {\r\n // return [\r\n // Token.$Http,\r\n // Token.$Q,\r\n // ApiService\r\n // ];\r\n // }\r\n\r\n public adminProducts: AdminProductClient =\r\n new AdminProductClient(this.$http, this.$q, \"/api/admin/products\");\r\n public automationStudio: AutomationStudioClient =\r\n new AutomationStudioClient(this.$http, this.$q, \"/api/automationstudio\");\r\n public builders: CrudClient =\r\n new CrudClient(this.$http, this.$q, \"/api/builders\");\r\n public buildTypes: CrudClient =\r\n new CrudClient(this.$http, this.$q, \"/api/buildtypes\");\r\n public builderSettings: SingletonCrudClient =\r\n new SingletonCrudClient(this.$http, this.$q, \"/api/buildersettings\");\r\n public categories: CategoriesClient =\r\n new CategoriesClient(this.$http, this.$q, \"/api/categories\");\r\n public changePassword: CrudClient =\r\n new CrudClient(this.$http, this.$q, \"/api/users/changepassword\");\r\n public channels: CrudClient =\r\n new CrudClient(this.$http, this.$q, \"/api/channels\");\r\n public companies: CrudClient =\r\n new CrudClient(this.$http, this.$q, \"/api/companies\");\r\n public configurators: ConfiguratorClient =\r\n new ConfiguratorClient(this.$http, this.$q, \"/api/admin/products\");\r\n public contacts: CrudClient =\r\n new CrudClient(this.$http, this.$q, \"/api/contacts\");\r\n public currencies: CurrencyClient =\r\n new CurrencyClient(this.$http, this.$q, \"/api/currencies\");\r\n public customActions: CrudClient =\r\n new CrudClient(this.$http, this.$q, \"/api/customactions\");\r\n public customers: CrudClient = new CrudClient(this.$http, this.$q, \"/api/customers\");\r\n public dashboard: SingletonCrudClient =\r\n new SingletonCrudClient(this.$http, this.$q, \"/api/dashboard\");\r\n public dbTables: DbTablesClient =\r\n new DbTablesClient(this.$http, this.$q, \"/api/dbtables\");\r\n public deployments: DeploymentClient =\r\n new DeploymentClient(this.$http, this.$q, \"/api/deployments\");\r\n public emailTemplates: CrudClient =\r\n new CrudClient(this.$http, this.$q, \"/api/emailtemplates\");\r\n public functions: CrudClient =\r\n new CrudClient(this.$http, this.$q, \"/api/functions\");\r\n public generators: GeneratorClient =\r\n new GeneratorClient(this.$http, this.$q, \"/api/generators\");\r\n public globalDefinitions: CrudClient =\r\n new CrudClient(this.$http, this.$q, \"/api/globaldefinitions\");\r\n public integrationSettings: IntegrationSettingsClient =\r\n new IntegrationSettingsClient(this.$http, this.$q, \"/api/integrationsettings\");\r\n public jobs: JobsClient =\r\n new JobsClient(this.$http, this.$q, \"/api/jobs\");\r\n public kinetic: KineticClient =\r\n new KineticClient(this.$http, this.$q, \"/api/kinetic\");\r\n public languages: LanguageClient =\r\n new LanguageClient(this.$http, this.$q, \"/api/languages\");\r\n public layouts: LayoutClient =\r\n new LayoutClient(this.$http, this.$q, \"/api/layouts\");\r\n public logs: CrudClient =\r\n new CrudClient(this.$http, this.$q, \"/api/logs\");\r\n public notifications: NotificationClient =\r\n new NotificationClient(this.$http, this.$q, \"/api/notifications\");\r\n public notificationSettings: SingletonCrudClient =\r\n new SingletonCrudClient(this.$http, this.$q, \"/api/notificationsettings\");\r\n public optionFilters: OptionFilterClient =\r\n new OptionFilterClient(this.$http, this.$q, \"/api/optionfilters\");\r\n public outputBuilders: CrudClient =\r\n new CrudClient(this.$http, this.$q, \"/api/builders\");\r\n public permissions: PermissionClient =\r\n new PermissionClient(this.$http, this.$q, \"/api/permissions\");\r\n public priceColumns: PriceColumnClient =\r\n new PriceColumnClient(this.$http, this.$q, \"/api/pricecolumns\");\r\n public products: ProductClient =\r\n new ProductClient(this.$http, this.$q, \"/api/products\");\r\n public productHistory: ProductHistoryClient =\r\n new ProductHistoryClient(this.$http, this.$q, \"/api/producthistory\");\r\n public productRules: SingletonCrudClient =\r\n new SingletonCrudClient(this.$http, this.$q, \"/api/productrules\");\r\n public queues: CrudClient =\r\n new CrudClient(this.$http, this.$q, \"/api/queues\");\r\n public quoteHeaders: QuoteHeaderClient =\r\n new QuoteHeaderClient(this.$http, this.$q, \"/api/quoteheaders\");\r\n public quoteOutputs: CrudClient =\r\n new CrudClient(this.$http, this.$q, \"/api/quoteoutputs\");\r\n public quotes: QuoteClient =\r\n new QuoteClient(this.$http, this.$q, \"/api/quotes\");\r\n public quoteProducts: CrudClient =\r\n new CrudClient(this.$http, this.$q, \"/api/quoteproducts\");\r\n public roles: CrudClient =\r\n new CrudClient(this.$http, this.$q, \"/api/roles\");\r\n public safeFunctions: SafeFunctionClient =\r\n new SafeFunctionClient(this.$http, this.$q, \"/api/functions\");\r\n public savedSearches: SavedSearchClient =\r\n new SavedSearchClient(this.$http, this.$q, \"/api/savedsearches\");\r\n public scenes: ScenesClient =\r\n new ScenesClient(this.$http, this.$q, this.$rootScope, \"/api/scenes\");\r\n public sceneHistory: SceneHistoryClient = \r\n new SceneHistoryClient(this.$http, this.$q, '/api/scenehistory');\r\n public settings: CompanySettingsClient =\r\n new CompanySettingsClient(this.$http, this.$q, \"/api/settings\");\r\n public tables: TablesClient =\r\n new TablesClient(this.$http, this.$q, \"/api/tables\");\r\n public tags: CrudClient =\r\n new CrudClient(this.$http, this.$q, \"/api/tags\");\r\n public testBuilds: TestBuildClient =\r\n new TestBuildClient(this.$http, this.$q, \"/api/testbuilds\");\r\n public themes: CrudClient =\r\n new CrudClient(this.$http, this.$q, \"/api/themes\");\r\n public tools: ToolsClient =\r\n new ToolsClient(this.$http, this.$q, \"api/tools\");\r\n public translate: TranslateClient =\r\n new TranslateClient(this.$http, this.$q, \"api/translate\");\r\n public users: UserClient =\r\n new UserClient(this.$http, this.$q, \"/api/users\");\r\n public workflows: WorkflowsClient =\r\n new WorkflowsClient(this.$http, this.$q, \"/api/workflows\");\r\n public workflowSelectors: SingletonCrudClient =\r\n new SingletonCrudClient(this.$http, this.$q, \"/api/workflowselector\");\r\n public dbWhitelist: DbWhitelistClient =\r\n new DbWhitelistClient(this.$http, this.$q, \"/api/dbwhitelist\");\r\n public dbXuserCreds: DbXuserCred =\r\n new DbXuserCred(this.$http, this.$q, \"/api/dbxuser\");\r\n public interactions: CrudClient =\r\n new CrudClient(this.$http, this.$q, \"/api/interactions\");\r\n public kineticMom: KineticMomClient =\r\n new KineticMomClient(this.$http, this.$q, \"/api/mom\");\r\n\r\n public getProxyClient(entityTypeName: string, admin: boolean): IProxyClient {\r\n let t = entityTypeName.toCamelCase();\r\n if (t.startsWith(\"kb\")) t = t.substr(2);\r\n if (t.toLowerCase() == \"useredit\") t = \"user\";\r\n t = t.endsWith(\"y\") ? t.substr(0, t.length - 1) + \"ies\" : t + \"s\";\r\n if (t.startsWith(\"company\")) t = t.substr(7);\r\n t = t.toCamelCase();\r\n let service = this[t];\r\n\r\n if (admin) {\r\n if (service == this.products) service = this.adminProducts;\r\n if (t.toLowerCase() == \"companysettings\") service = this.settings;\r\n }\r\n return service;\r\n }\r\n}\r\n\r\nexport class CrudClient implements IProxyClient {\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseUrl) {\r\n\r\n }\r\n\r\n public getById(id: number, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.get(`${this.baseUrl}/${id}`, { tracker }).then(r => r.data);\r\n }\r\n\r\n public getFromEnvironment(id: number, env: string, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.get(`${this.baseUrl}/${id}/diff`, { params: { env }, tracker }).then(r => r.data);\r\n }\r\n\r\n public edit(model: TModel, tracker?: ng.IPromiseTracker, waitForRefresh = false): ng.IPromise {\r\n return this.$http.put(`${this.baseUrl}/${model.id}?waitForRefresh=${waitForRefresh}`, model, { tracker }).then(r => r.data);\r\n }\r\n\r\n public insert(model: TModel, tracker?: ng.IPromiseTracker, waitForRefresh = false): ng.IPromise {\r\n return this.$http.post(`${this.baseUrl}?waitForRefresh=${waitForRefresh}`, model, { tracker }).then(r => r.data);\r\n }\r\n\r\n public upsert(model: TModel, tracker?: ng.IPromiseTracker, waitForRefresh = false): ng.IPromise {\r\n if (model.id) {\r\n return this.edit(model, tracker, waitForRefresh);\r\n } else {\r\n return this.insert(model, tracker, waitForRefresh);\r\n }\r\n }\r\n\r\n public delete(id: number, tracker?: ng.IPromiseTracker, ignoreSecurity: boolean = false): ng.IPromise {\r\n return this.$http.delete(`${this.baseUrl}/${id}`, { tracker, ignoreSecurity });\r\n }\r\n\r\n public clone(id: number, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.post(`${this.baseUrl}/${id}/clone`, null, { tracker }).then(r => r.data);\r\n }\r\n\r\n public getPaged(p: kb.IPagingRequest, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.get>(this.baseUrl, { params: p, tracker }).then(r => r.data.items);\r\n }\r\n\r\n public searchPaged(p: kb.IPagingRequest, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.post>(this.baseUrl + \"/searchPaged\", p).then(r => r.data.items);\r\n }\r\n\r\n public getBatch(request: kb.IBatchRequest, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.get(`${this.baseUrl}/batch`, { params: request, tracker }).then(r => r.data);\r\n }\r\n\r\n public search(args?: kb.ISearchArgs, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n // fill in args with defaults\r\n let defaultArgs: kb.ISearchArgs = {\r\n query: null,\r\n fields: null,\r\n sortField: \"name\",\r\n descending: false,\r\n skip: 0,\r\n take: 10000\r\n };\r\n\r\n let fullArgs = Utils.extend({}, defaultArgs, args);\r\n return this.$http.post(`${this.baseUrl}/search`, fullArgs, { tracker }).then(r => r.data);\r\n }\r\n\r\n public suggest(args: kb.ISuggestArgs): ng.IPromise {\r\n if (args.query) {\r\n return this.$http.post(`${this.baseUrl}/suggest`, args).then(r => r.data);\r\n } else {\r\n return this.$q.when([]);\r\n }\r\n }\r\n\r\n public uniqueValues(args: kb.IUniqueValuesArgs): ng.IPromise {\r\n return this.$http.post(`${this.baseUrl}/uniquevalues`, args).then(r => r.data);\r\n }\r\n\r\n public rebuildIndex(tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.post(`${this.baseUrl}/rebuildindex`, null, { tracker });\r\n }\r\n}\r\n\r\nexport class AutomationStudioClient {\r\n\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseUrl) {\r\n\r\n }\r\n\r\n public getToken(tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.get(`${this.baseUrl}/token`, { tracker }).then(r => r.data);\r\n }\r\n}\r\n\r\nexport class TranslateClient {\r\n\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseUrl) {\r\n\r\n }\r\n\r\n public translateArray(request: kb.ITranslateArrayRequest, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.post(`${this.baseUrl}/array`, request, { tracker }).then(r => r.data);\r\n }\r\n}\r\n\r\nexport class DeploymentClient {\r\n\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseUrl) {\r\n\r\n }\r\n\r\n public getById(id: number, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.get(`${this.baseUrl}/${id}`, { tracker }).then(r => r.data);\r\n }\r\n\r\n public getPaged(p: kb.IPagingRequest, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.get>(this.baseUrl, { params: p, tracker })\r\n .then(r => r.data.items);\r\n }\r\n\r\n public deploy(model: kb.IDeployment): ng.IPromise {\r\n return this.$http.post(\"/api/deploy\", model).then(r => r.data);\r\n }\r\n\r\n public compare(model: kb.IDeployment, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.post(\"/api/deploy/compare\", model, { tracker }).then(r => r.data);\r\n }\r\n}\r\n\r\nexport class SingletonCrudClient implements IProxyClient {\r\n\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseUrl) {\r\n\r\n }\r\n\r\n public get(tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.get(`${this.baseUrl}`, { tracker }).then(r => r.data);\r\n }\r\n\r\n public edit(model: TModel, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.put(`${this.baseUrl}`, model, { tracker }).then(r => r.data);\r\n }\r\n\r\n public getFromEnvironment(id: number, env: string, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.get(`${this.baseUrl}/diff`, { params: { env }, tracker }).then(r => r.data);\r\n }\r\n\r\n public rebuildIndex(tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.post(`${this.baseUrl}/rebuildindex`, null, { tracker });\r\n }\r\n}\r\n\r\nexport class PermissionClient {\r\n\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseUrl) {\r\n\r\n }\r\n\r\n public get(tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.get(`${this.baseUrl}`, { tracker }).then(r => r.data);\r\n }\r\n\r\n public save(model: kb.IPermission[], tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.post(`${this.baseUrl}`, model, { tracker }).then(r => r.data);\r\n }\r\n\r\n}\r\n\r\nexport class ToolsClient {\r\n\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseUrl) {\r\n\r\n }\r\n\r\n public runIndexOperation(args: kb.IAdminIndexOperationArgs, tracker?: ng.IPromiseTracker): ng.IPromise{\r\n return this.$http.post(`/api/search/run`, args, { tracker }).then(r => r.data);\r\n }\r\n\r\n public rebuildIndex(tracker?: ng.IPromiseTracker): ng.IHttpPromise {\r\n return this.$http.post(`/api/search/rebuild`, null, { tracker });\r\n }\r\n\r\n public rebuildIndexAllEnv(tracker?: ng.IPromiseTracker): ng.IHttpPromise {\r\n return this.$http.post(`/api/search/rebuildallenv`, null, { tracker });\r\n }\r\n\r\n public rebuildIndexAll(tracker?: ng.IPromiseTracker): ng.IHttpPromise {\r\n return this.$http.post(`/api/search/rebuildall`, null, { tracker });\r\n }\r\n\r\n public rebuildRootIndex(tracker?: ng.IPromiseTracker): ng.IHttpPromise {\r\n return this.$http.post(`/api/search/rebuildroot`, null, { tracker });\r\n }\r\n\r\n public recreateStorage(tracker?: ng.IPromiseTracker): ng.IHttpPromise {\r\n return this.$http.post(`/api/storage/create`, null, { tracker });\r\n }\r\n\r\n public pullFromProduction(tracker?: ng.IPromiseTracker): ng.IHttpPromise {\r\n return this.$http.post(`${this.baseUrl}/pullfromprod`, null, { tracker });\r\n }\r\n\r\n public update3DPlugin(tracker?: ng.IPromiseTracker): ng.IHttpPromise {\r\n return this.$http.post(`/api/debug/post-3d-plugin`, null, { tracker });\r\n }\r\n\r\n public recreate3D(tracker?: ng.IPromiseTracker): ng.IHttpPromise {\r\n return this.$http.post(`/api/recreate3d`, null, { tracker });\r\n }\r\n\r\n public recreateDns(tracker?: ng.IPromiseTracker): ng.IHttpPromise {\r\n return this.$http.post(`/api/recreatedns`, null, { tracker });\r\n }\r\n\r\n public cleanDb(args: kb.ICleanDbQueueMessage, tracker?: ng.IPromiseTracker): ng.IHttpPromise {\r\n return this.$http.post(\"${this.baseUrl}/cleanDb\", args, { tracker });\r\n }\r\n\r\n public pullSfdcProducts(soqlStatement: string, tracker?: ng.IPromiseTracker): ng.IHttpPromise {\r\n return this.$http.post(`${this.baseUrl}/pullsfdcproducts`, { whereClause: soqlStatement }, { tracker });\r\n }\r\n\r\n public getSearchableTypeNames(tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.get(`/api/search/searchableTypes`, { tracker }).then(r => r.data);\r\n }\r\n}\r\n\r\nexport class PriceColumnClient extends CrudClient {\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseUrl) {\r\n super($http, $q, baseUrl);\r\n }\r\n\r\n public getPriceColumnsForUser(tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.get(`${this.baseUrl}/user`).then(r => r.data);\r\n }\r\n\r\n public reorder(args: kb.IPriceColumnReorder[], tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.post(`${this.baseUrl}/reorder`, args, { tracker }).then(r => r.data);\r\n }\r\n}\r\n\r\nexport class KineticClient {\r\n\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseUrl) {\r\n\r\n }\r\n\r\n public getDocumentRulesSchema(idConfig: number): ng.IHttpPromise {\r\n return this.$http.get(`${this.baseUrl}/documentRuleSchema/${idConfig}`, null);\r\n }\r\n\r\n public getDocumentRulesSchemaForDynamicAttributes(idConfig: number, company: string): ng.IHttpPromise {\r\n return this.$http.get(`${this.baseUrl}/documentRuleSchema/${idConfig}/${company}`, null);\r\n }\r\n\r\n public testConnection(): ng.IHttpPromise {\r\n return this.$http.get(`${this.baseUrl}/test`, null);\r\n }\r\n}\r\n\r\nexport class JobsClient extends CrudClient {\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseUrl) {\r\n super($http, $q, baseUrl);\r\n }\r\n\r\n public getLogs(idJob: number, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.get(`${this.baseUrl}/${idJob}/logs`).then(r => r.data);\r\n }\r\n}\r\n\r\n\r\nexport class TablesClient extends CrudClient {\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseUrl) {\r\n super($http, $q, baseUrl);\r\n }\r\n\r\n public updateFromSource(id: number, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.post(`${this.baseUrl}/${id}/updatefromsource`, null, { tracker }).then(r => r.data);\r\n }\r\n}\r\n\r\nexport class WorkflowsClient extends CrudClient {\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseUrl) {\r\n super($http, $q, baseUrl);\r\n }\r\n\r\n public states(tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.get(`/api/states`, { tracker }).then(r => r.data);\r\n }\r\n}\r\n\r\nexport class ScenesClient extends CrudClient {\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public $rootScope: IRootScope, public baseUrl) {\r\n super($http, $q, baseUrl);\r\n }\r\n\r\n public search(args?: kb.ISearchArgs, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n args = args || {};\r\n args.filters = args.filters || [];\r\n\r\n let externalValues = [];\r\n if (this.$rootScope.company.kb3dEnabled) externalValues.push(false);\r\n if (this.$rootScope.company.classic3dEnabled) externalValues.push(true);\r\n args.filters.push({\r\n property: \"external\",\r\n values: externalValues\r\n });\r\n \r\n return super.search(args, tracker);\r\n }\r\n\r\n public convertToKb3d(id: number, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.post(`${this.baseUrl}/${id}/convert`, null, { tracker }).then(r => r.data);\r\n }\r\n}\r\n\r\nexport class SceneHistoryClient {\r\n\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseUrl) {\r\n\r\n }\r\n\r\n public getSceneHistory(idScene: number, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.get(`${this.baseUrl}/${idScene}`, { tracker }).then(r => r.data);\r\n }\r\n\r\n public getHistoryByIdHistory(idHistory: number, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.get(`${this.baseUrl}/idhist/${idHistory}`, { tracker }).then(r => r.data);\r\n }\r\n\r\n public cloneHistoryToNewScene(idSceneHistory: number, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.post(`${this.baseUrl}/clone/${idSceneHistory}`, {}, { tracker }).then(r => r.data);\r\n }\r\n\r\n public revertSceneToHistory(idSceneHistory: number, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.post(`${this.baseUrl}/revert/${idSceneHistory}`, {}, { tracker }).then(r => r.data);\r\n }\r\n}\r\n\r\nexport class NotificationClient extends CrudClient {\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseUrl) {\r\n super($http, $q, baseUrl);\r\n }\r\n}\r\n\r\nexport class CategoriesClient extends CrudClient {\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseUrl) {\r\n super($http, $q, baseUrl);\r\n }\r\n\r\n public tree(params: {}, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.get(\"api/categories/tree\", { params, tracker }).then(r => r.data);\r\n }\r\n}\r\n\r\nexport class OptionFilterClient {\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseUrl) {\r\n\r\n }\r\n\r\n public run(args: kb.IOptionFilterRunArgs, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.post(`${this.baseUrl}/run`, args, { tracker }).then(r => r.data);\r\n }\r\n}\r\n\r\nexport class DbTablesClient {\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseUrl) {\r\n\r\n }\r\n\r\n public getAll(tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.get(`${this.baseUrl}`, { tracker }).then(r => r.data);\r\n }\r\n\r\n public get(name: string, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.get(`${this.baseUrl}/${name}`, { tracker }).then(r => r.data);\r\n }\r\n\r\n public getAllSizeInfo(tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.get(`${this.baseUrl}/sizes`, { tracker }).then(r => r.data);\r\n }\r\n}\r\n\r\nexport class IntegrationSettingsClient extends SingletonCrudClient {\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseUrl) {\r\n super($http, $q, baseUrl);\r\n }\r\n\r\n public checkSfdcCredentials(): ng.IPromise {\r\n return this.$http.get(`/api/integrationsettings/checksfdccredentials`).then(r => r.data);\r\n }\r\n\r\n public checkOracleCpqCredentials(): ng.IPromise {\r\n return this.$http.get(`/api/integrationsettings/checkoraclecpqcredentials`).then(r => r.data);\r\n }\r\n\r\n public getSsoGroups(keywords:string): ng.IPromise {\r\n return this.$http.get(`/api/integrationsettings/ssogroups?keywords=${keywords}`).then(r => r.data);\r\n }\r\n\r\n public getSsoGroupById(groupId: string): ng.IPromise {\r\n return this.$http.get(`/api/integrationsettings/ssogroup/${groupId}`).then(r => r.data);\r\n }\r\n}\r\n\r\nexport class CurrencyClient extends CrudClient {\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseUrl) {\r\n super($http, $q, baseUrl);\r\n }\r\n\r\n /**\r\n * gets all company currencies\r\n * @param tracker\r\n */\r\n public all(tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.get(`${this.baseUrl}/all`, { tracker }).then(r => r.data);\r\n }\r\n\r\n /**\r\n * gets a list of all currencies (not just company currencies). \r\n * Used for populating a select box to add new currencies.\r\n * @param tracker\r\n */\r\n public options(tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.get(`${this.baseUrl}/options`, { tracker }).then(r => r.data);\r\n }\r\n\r\n /**\r\n * gets a list of company currencies that also includes the base currency. \r\n * Used for populating a select box in the quote screen for example.\r\n * @param tracker\r\n */\r\n public companyOptions(tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.get(`${this.baseUrl}/companyoptions`, { tracker }).then(r => r.data);\r\n }\r\n\r\n /**\r\n * saves the company currencies.\r\n * @param companyCurrencies\r\n * @param tracker\r\n */\r\n public save(\r\n companyCurrencies: kb.ICompanyCurrency[],\r\n tracker?: ng.IPromiseTracker\r\n ): ng.IPromise {\r\n return this.$http.post(`${this.baseUrl}/save`, companyCurrencies, { tracker })\r\n .then(r => r.data);\r\n }\r\n\r\n public getExchangeRates(baseCurrency?: string, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.get(`${this.baseUrl}/exchangerates/${baseCurrency || \"\"}`, { tracker }).then(r => r.data);\r\n }\r\n}\r\n\r\nexport class LanguageClient extends CrudClient {\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseUrl) {\r\n super($http, $q, baseUrl);\r\n }\r\n\r\n /**\r\n * gets a list of all languages supported by CPQ (not just company languages). \r\n * Used for populating a select box to add new languages.\r\n * @param tracker\r\n */\r\n public supportedLanguages(tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.get(`${this.baseUrl}/supported`, { tracker }).then(r => r.data);\r\n }\r\n \r\n}\r\n\r\nexport class GeneratorClient extends CrudClient {\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseUrl) {\r\n super($http, $q, baseUrl);\r\n }\r\n\r\n public next(id: number, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.get(`${this.baseUrl}/${id}/next`, { tracker }).then(r => r.data);\r\n }\r\n}\r\n\r\nexport class UserClient extends CrudClient {\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseUrl) {\r\n super($http, $q, baseUrl);\r\n }\r\n\r\n public clearProfileImage(userId: number): ng.IPromise {\r\n return this.$http.delete(`/api/users/profileimage/${userId}`).then(r => r.data);\r\n }\r\n\r\n public deleteAndAnonymize(userId: number): ng.IPromise {\r\n return this.$http.delete(`/api/users/anonymize/${userId}`).then(r => r.data);\r\n }\r\n\r\n public resetPassword(userId: number): ng.IPromise {\r\n return this.$http.post(\r\n \"api/users/resetpassword/\" + userId, {}).then(r => r.data);\r\n }\r\n\r\n public acceptPrivacyPolicy(): ng.IPromise {\r\n return this.$http.post(\r\n \"api/users/acceptprivacypolicy\", {}).then(r => r.data);\r\n }\r\n\r\n public resetDeactivation(userId: number): ng.IPromise {\r\n return this.$http.put(\r\n \"api/users/resetdeactivation/\" + userId, {}).then(r => r.data);\r\n }\r\n}\r\n\r\nexport class LayoutClient extends CrudClient {\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseUrl) {\r\n super($http, $q, baseUrl);\r\n }\r\n\r\n public selections(tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.get(`${this.baseUrl}/selections`, { tracker }).then(r => r.data);\r\n }\r\n}\r\n\r\nexport class DbWhitelistClient {\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseUrl: string) {\r\n\r\n }\r\n\r\n public add(entry:kb.IDbWhitelistEntry, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.post(\r\n this.baseUrl, entry).then(r => r.data);\r\n }\r\n\r\n public getAll(tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.get(this.baseUrl).then(r => r.data);\r\n }\r\n\r\n public delete(name: string, tracker?: ng.IPromiseTracker) {\r\n return this.$http.delete(this.baseUrl + \"/\" + name).then(r => r.data);\r\n }\r\n}\r\n\r\nexport class DbXuserCred {\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseurl: string) {\r\n\r\n }\r\n\r\n public post() {\r\n return this.$http.post(this.baseurl, null).then(r => r.data);\r\n }\r\n}\r\n\r\nexport class KineticMomClient {\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseUrl: string) {\r\n\r\n }\r\n\r\n public get(idConfigurator:number, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.get(\r\n this.baseUrl + \"/partRev/\" + idConfigurator).then(r => r.data);\r\n }\r\n}\r\n\r\nexport class ConfiguratorClient extends CrudClient {\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseUrl) {\r\n super($http, $q, baseUrl);\r\n }\r\n\r\n public search(args?: kb.ISearchArgs, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n args = args || {};\r\n args.filters = args.filters || [];\r\n args.filters.push({\r\n property: meta.Product.isConfigured.name,\r\n values: [true]\r\n });\r\n return super.search(args, tracker);\r\n }\r\n\r\n public searchFields(id: number): ng.IPromise<{ id: string; name: string; type: string }[]> {\r\n return this.$http.get<{ id: string; name: string; type: string }[]>(`/api/products/${id}/searchfields`)\r\n .then(r => r.data);\r\n }\r\n}\r\n\r\nexport class AdminProductClient extends CrudClient {\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseUrl) {\r\n super($http, $q, baseUrl);\r\n }\r\n\r\n public search(args?: kb.ISearchArgs, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n args = args || {};\r\n args.filters = args.filters || [];\r\n args.filters.push(ProductClient.getIsConfiguredFilter(false));\r\n return super.search(args, tracker);\r\n }\r\n\r\n public getOutput(idProduct: number, idOutput: string, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.get(`/api/admin/products/${idProduct}/output/${idOutput}`).then(r => r.data);\r\n }\r\n}\r\n\r\nexport class ProductHistoryClient {\r\n\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseUrl) {\r\n\r\n }\r\n\r\n public getProductHistory(idProduct: number, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.get(`${this.baseUrl}/${idProduct}`, { tracker }).then(r => r.data);\r\n }\r\n\r\n public getHistoryByIdHistory(idHistory: number, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.get(`${this.baseUrl}/idhist/${idHistory}`, { tracker }).then(r => r.data);\r\n }\r\n\r\n public cloneHistoryToNewProduct(idProductHistory: number, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.post(`${this.baseUrl}/clone/${idProductHistory}`, {}, { tracker }).then(r => r.data);\r\n }\r\n\r\n public revertProductToHistory(idProductHistory: number, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.post(`${this.baseUrl}/revert/${idProductHistory}`, {}, { tracker }).then(r => r.data);\r\n }\r\n}\r\n\r\nexport class ProductClient extends CrudClient {\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseUrl) {\r\n super($http, $q, baseUrl);\r\n }\r\n\r\n public run(id: number, isTest: boolean, fast: boolean, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n let path = (fast ? `runfast` : `run?test=${isTest}`);\r\n return this.$http.get(`${this.baseUrl}/${id}/${path}`, { tracker }).then(r => r.data);\r\n }\r\n\r\n public autocomplete(\r\n productId: number,\r\n fieldId: string,\r\n query: string,\r\n tracker?: ng.IPromiseTracker\r\n ): ng.IPromise {\r\n return this.$http.get(`${this.baseUrl}/${productId}/autocomplete`, {\r\n params: { field: fieldId, query },\r\n tracker\r\n }).then(r => r.data);\r\n }\r\n\r\n public searchByCategory(args?: kb.IProductSearchArgs, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.post(\r\n \"/api/products/searchByCategory\",\r\n args,\r\n { tracker }\r\n ).then(r => r.data);\r\n }\r\n\r\n public static getIsConfiguredFilter(isConfigured: boolean): kb.IFilter {\r\n return {\r\n property: meta.Product.isConfigured.name,\r\n values: [isConfigured]\r\n };\r\n }\r\n\r\n public uniqueAttributeValues(args: kb.IUniqueAttributeValuesArgs): ng.IPromise {\r\n return this.$http.post(`${this.baseUrl}/uniqueattributevalues`, args).then(r => r.data);\r\n }\r\n\r\n public attributeRanges(args: kb.IAttributeRangeArgs): ng.IPromise {\r\n return this.$http.post(`${this.baseUrl}/attributeranges`, args).then(r => r.data);\r\n }\r\n}\r\n\r\nexport class SafeFunctionClient extends CrudClient {\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseUrl) {\r\n super($http, $q, baseUrl);\r\n }\r\n\r\n public run(id: number, parameters?: {}, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.post(`${this.baseUrl}/run/${id}`, parameters, { tracker }).then(r => {\r\n if (r.status == 204) return null; //no content result should be null to be backwards compatible\r\n return r.data\r\n });\r\n }\r\n\r\n public test(id: number, args?: string, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.post(`${this.baseUrl}/test/${id}`, args, { tracker }).then(r => {\r\n if (r.status == 204) return null; //no content result should be null to be backwards compatible\r\n return r.data\r\n });\r\n }\r\n}\r\n\r\nexport class QuoteClient extends CrudClient {\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseUrl) {\r\n super($http, $q, baseUrl);\r\n }\r\n\r\n public save(quote: kb.IQuote, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.post(`${this.baseUrl}/save`, quote, { tracker }).then(r => r.data);\r\n }\r\n\r\n public getProductBuildTypes(idQuote: number, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.get(`${this.baseUrl}/${idQuote}/productBuildTypes`, { tracker }).then(r => r.data);\r\n }\r\n\r\n public copyQuoteProduct(\r\n idQuote: number,\r\n idQuoteProduct: number,\r\n tracker?: ng.IPromiseTracker\r\n ): ng.IPromise {\r\n return this.$http.post(`${this.baseUrl}/${idQuote}/product/${idQuoteProduct}/copy`, null, { tracker })\r\n .then(r => r.data);\r\n }\r\n\r\n public getQuoteProduct(\r\n idQuote: number,\r\n idQuoteProduct: number,\r\n tracker?: ng.IPromiseTracker\r\n ): ng.IPromise {\r\n return this.$http.get(`${this.baseUrl}/${idQuote}/product/${idQuoteProduct}`, { tracker })\r\n .then(r => r.data);\r\n }\r\n\r\n public insertQuoteProduct(\r\n idQuote: number,\r\n quoteProduct: kb.IQuoteProduct,\r\n tracker?: ng.IPromiseTracker\r\n ): ng.IPromise {\r\n return this.$http.post(`${this.baseUrl}/${idQuote}/product`, quoteProduct, { tracker })\r\n .then(r => r.data);\r\n }\r\n\r\n public editQuoteProduct(\r\n idQuote: number,\r\n quoteProduct: kb.IQuoteProduct,\r\n tracker?: ng.IPromiseTracker\r\n ): ng.IPromise {\r\n return this.$http.put(`${this.baseUrl}/${idQuote}/product/${quoteProduct.id}`, quoteProduct, { tracker })\r\n .then(r => r.data);\r\n }\r\n\r\n public buildQuoteProduct(\r\n idQuote: number,\r\n idQuoteProduct: number,\r\n idBuildType: number,\r\n tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.post(`${this.baseUrl}/${idQuote}/product/${idQuoteProduct}/build/${idBuildType}`, {}, { tracker }).then(r => r.data);\r\n }\r\n\r\n public deleteQuoteProduct(\r\n idQuote: number,\r\n quoteProduct: kb.IQuoteProduct,\r\n tracker?: ng.IPromiseTracker\r\n ): ng.IPromise {\r\n return this.$http.delete(`${this.baseUrl}/${idQuote}/product/${quoteProduct.id}`, { tracker })\r\n .then(r => r.data);\r\n }\r\n\r\n public submit(quote: kb.IQuote, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.post(`${this.baseUrl}/submit`, quote, { tracker }).then(r => r.data);\r\n }\r\n\r\n public runQuoteHeaderRule(quote: kb.IQuote, tracker?: ng.IPromiseTracker): ng.IPromise {\r\n return this.$http.post(`${this.baseUrl}/headerrule`, quote, { tracker }).then(r => r.data);\r\n }\r\n}\r\n\r\nexport class SavedSearchClient extends CrudClient {\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseUrl) {\r\n super($http, $q, baseUrl);\r\n }\r\n\r\n public mySearches(modelType: string): ng.IPromise {\r\n return this.$http.get(`${this.baseUrl}/${modelType}`).then(r => r.data);\r\n }\r\n}\r\n\r\nexport class TestBuildClient extends CrudClient {\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseUrl) {\r\n super($http, $q, baseUrl);\r\n }\r\n\r\n public getQueue(config: kb.IConfiguredProduct, buildId: string): ng.IPromise {\r\n return this.$http.post(`${this.baseUrl}/${buildId}/queue`, {\r\n config\r\n }).then(r => r.data);\r\n }\r\n}\r\n\r\nexport class CompanySettingsClient extends SingletonCrudClient {\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseUrl) {\r\n super($http, $q, baseUrl);\r\n }\r\n\r\n public updateSfdcCredential(\r\n apiUsername: string,\r\n apiPassword: string,\r\n apiToken: string): ng.IPromise {\r\n return this.$http.post(`${this.baseUrl}/sfdc-credential`, {\r\n sfdcApiUsername: apiUsername,\r\n sfdcApiPassword: apiPassword,\r\n sfdcApiToken: apiToken\r\n });\r\n }\r\n\r\n public editCurrencySetting(\r\n currencySetting: kb.ICurrencySetting,\r\n tracker?: ng.IPromiseTracker\r\n ): ng.IPromise {\r\n return this.$http.put(`${this.baseUrl}/currency`, currencySetting, { tracker })\r\n .then(r => r.data);\r\n }\r\n}\r\n\r\nexport class QuoteHeaderClient extends CrudClient {\r\n constructor(public $http: ng.IHttpService, public $q: ng.IQService, public baseUrl) {\r\n super($http, $q, baseUrl);\r\n }\r\n\r\n public getDefault(): ng.IPromise {\r\n return this.$http.get(`${this.baseUrl}/default`).then(r => r.data);\r\n }\r\n\r\n public searchFields(): ng.IPromise<{ id: string; name: string; type: string }[]> {\r\n return this.$http.get<{ id: string; name: string; type: string }[]>(`/api/quoteheaders/searchfields`)\r\n .then(r => r.data);\r\n }\r\n}\r\n","import { NgService } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { SecurityRetryService } from \"@app/services/security-retry.service\";\r\nimport { SignalrService } from \"@app/services/signalr.service\";\r\nimport { eAlertType, IClientContext, IDialogService, IKbRole, IRootScope, IScene, IUser } from \"@models\";\r\nimport { events } from \"@tools\";\r\nimport { StateService } from \"@uirouter/core\";\r\nimport { StorageService } from \"./storage.service\";\r\n\r\nexport interface IAuthService {\r\n authPromise: ng.IPromise;\r\n\r\n // loadCompany: () => ng.IPromise;\r\n // loadUser: () => ng.IPromise;\r\n loadContext: () => ng.IPromise;\r\n // loadExchangeRates: () => ng.IPromise;\r\n\r\n login: (email: string, password: string, rememberMe: boolean) => ng.IHttpPromise;\r\n logout: () => void;\r\n confirmLogin: (user: IUser) => void;\r\n loginError: string;\r\n\r\n // canUser(permissionId: string): boolean;\r\n hasRole(role: string): boolean;\r\n userHasRole(user: any, role: string): boolean;\r\n // isAdmin(): boolean;\r\n // userIsAdmin(user: IUser): boolean;\r\n isAdminOrCompanyAdmin(): boolean;\r\n}\r\n\r\n@NgService({\r\n token: Token.AuthService,\r\n dependencies: [\r\n Token.$Http,\r\n Token.SecurityRetryService,\r\n Token.$RootScope,\r\n Token.$Q,\r\n Token.SignalRService,\r\n Token.DialogService,\r\n Token.$State,\r\n Token.StorageService\r\n ]\r\n})\r\nexport class AuthService {\r\n\r\n constructor(\r\n private $http: ng.IHttpService,\r\n private securityRetryQueue: SecurityRetryService,\r\n private $rootScope: IRootScope,\r\n private $q: ng.IQService,\r\n private signalrService: SignalrService,\r\n private dialogService: IDialogService,\r\n private $state: StateService,\r\n private storageService: StorageService\r\n ) {\r\n\r\n // we need a promise that doesn't resolve until we have a real user. \r\n // Controllers can set this promise in the resolve property of the \r\n // route so that the controller won't initialize until we have a user\r\n let userDeferred = $q.defer();\r\n this.userPromise = userDeferred.promise;\r\n let contextDeferred = $q.defer();\r\n this.contextPromise = contextDeferred.promise;\r\n // var companyDeferred = $q.defer();\r\n // this.companyPromise = companyDeferred.promise;\r\n // var exchangeRatesDeferred = $q.defer();\r\n // this.exchangeRatesPromise = exchangeRatesDeferred.promise;\r\n // var companySettingsDeferred = $q.defer();\r\n // this.companySettingsPromise = companySettingsDeferred.promise;\r\n\r\n this.authPromise = $q.all([this.userPromise, this.contextPromise]);\r\n\r\n this.loadContext = () => {\r\n return $q.when((() => {\r\n let serverVm: { context: IClientContext; scene?: IScene; } = (window as any).serverVm;\r\n $rootScope.context = serverVm.context;\r\n $rootScope.environment = serverVm.context.environment;\r\n $rootScope.clusterEnv = serverVm.context.clusterEnv;\r\n $rootScope.cacheBuster = serverVm.context.cacheBuster;\r\n $rootScope.supportedLanguages = serverVm.context.supportedLanguages;\r\n $rootScope.clientLanguage = serverVm.context.clientLanguage;\r\n $rootScope.company = serverVm.context.company;\r\n $rootScope.companySettings = serverVm.context.companySettings;\r\n $rootScope.companyCurrencies = serverVm.context.companyCurrencies;\r\n fx.base = $rootScope.companySettings.currency.toUpperCase();\r\n fx.rates = {};\r\n $rootScope.companyCurrencies.forEach(cc => {\r\n fx.rates[cc.currency.toUpperCase()] = cc.rate;\r\n });\r\n $rootScope.kbmaxLogoPath = storageService.getAssetUrl('images/epicor_logo_white.png');\r\n if ($rootScope.context.channel && $rootScope.context.channel.imagePath) {\r\n $rootScope.companyLogoPath = storageService.getMediaUrl($rootScope.context.channel.imagePath);\r\n }\r\n else {\r\n $rootScope.companyLogoPath = $rootScope.companySettings.logoPath ? storageService.getMediaUrl($rootScope.companySettings.logoPath) : $rootScope.kbmaxLogoPath\r\n }\r\n\r\n if (serverVm.context.user) {\r\n this.confirmLogin(serverVm.context.user);\r\n }\r\n\r\n contextDeferred.resolve(serverVm.context);\r\n })());\r\n };\r\n\r\n this.login = (email: string, password: string, rememberMe: boolean) => {\r\n this.loginError = null;\r\n if ($rootScope.user) {\r\n this.logout();\r\n }\r\n return this.$http.post(\r\n \"/api/auth/login\",\r\n { email, password, rememberMe },\r\n { doNotReplay: true, tracker: $rootScope.loginTracker } as ng.IRequestConfig\r\n ).then(r => {\r\n this.confirmLogin(r.data);\r\n }, (r: ng.IHttpResponse) => {\r\n if (r.status == 400) {\r\n this.loginError = r.data[\"\"].join(\"\\n\");\r\n }\r\n });\r\n };\r\n\r\n this.logout = () => {\r\n this.$http.post(\"/api/auth/logout\", { doNotReplay: true } as ng.IRequestConfig).then(() => {\r\n // reload the whole page to clear all context\r\n window.location.reload();\r\n });\r\n // $rootScope.user = null;\r\n // $rootScope.$broadcast(events.loginRequested);\r\n };\r\n\r\n $rootScope.$on(events.loginRequested, e => {\r\n $rootScope.user = null;\r\n });\r\n\r\n $rootScope.$on(events.permissionDenied, e => {\r\n this.dialogService.alert({\r\n msg: \"Sorry, you do not have permission to view this.\",\r\n type: eAlertType.error\r\n });\r\n this.$state.go(\"kb.products\");\r\n });\r\n\r\n this.confirmLogin = user => {\r\n $rootScope.user = user;\r\n // resolve the deferred user promise\r\n userDeferred.resolve(user);\r\n\r\n this.securityRetryQueue.retryAll();\r\n\r\n if ($rootScope.user.id != -1) {\r\n this.signalrService.start().then(() => {\r\n $rootScope.$broadcast(events.loginSuccessful, $rootScope.user);\r\n });\r\n }\r\n else {\r\n $rootScope.$broadcast(events.loginSuccessful, $rootScope.user);\r\n }\r\n\r\n };\r\n\r\n this.keepAlive = () => {\r\n this.$http.get(\"/api/auth/keepalive\").then(() => {\r\n // reload the whole page to clear all context\r\n // window.location.reload();\r\n });\r\n }\r\n\r\n this.loadContext();\r\n }\r\n\r\n public static ANONYMOUS_USER_ID = -1;\r\n private userPromise: ng.IPromise;\r\n public contextPromise: ng.IPromise;\r\n public authPromise: ng.IPromise;\r\n\r\n public loadContext: () => ng.IPromise;\r\n public login: (email: string, password: string, rememberMe: boolean) => ng.IPromise;\r\n public logout: () => void;\r\n public confirmLogin: (user: IUser) => void;\r\n public loginError: string;\r\n public keepAlive: () => void;\r\n\r\n public hasRole(role: string): boolean {\r\n let isInRole = false;\r\n\r\n if (this.$rootScope.user) {\r\n isInRole = this.$rootScope.user.roles.some((r: IKbRole) => {\r\n return r.role.isEqual(role);\r\n });\r\n }\r\n return isInRole;\r\n }\r\n\r\n public userHasRole(user: IUser, role: string): boolean {\r\n let isInRole = user.roles.some((r: IKbRole) => {\r\n if (!r.role) return false;\r\n return r.role.isEqual(role);\r\n });\r\n\r\n return isInRole;\r\n }\r\n\r\n public isAdminOrCompanyAdmin(): boolean {\r\n let bret = false;\r\n if (this.$rootScope.user) {\r\n bret = this.hasRole(\"Company Administrator\") || this.$rootScope.user.isAdmin;\r\n }\r\n return bret;\r\n }\r\n\r\n}\r\n","import { NgService } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\n/**\r\n * base64 encoding from : http://www.webtoolkit.info/javascript-base64.html\r\n */\r\n@NgService({\r\n token: Token.Base64Service,\r\n dependencies: [\r\n ]\r\n})\r\nexport class Base64Service {\r\n constructor() {\r\n\r\n }\r\n\r\n private keyStr: string = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\";\r\n\r\n public encode(input: string): string {\r\n let output = \"\";\r\n let chr1: any;\r\n let chr2: any;\r\n let chr3: any;\r\n let enc1: any;\r\n let enc2: any;\r\n let enc3: any;\r\n let enc4: any;\r\n let i: number = 0;\r\n\r\n do {\r\n chr1 = input.charCodeAt(i++);\r\n chr2 = input.charCodeAt(i++);\r\n chr3 = input.charCodeAt(i++);\r\n\r\n // tslint:disable:no-bitwise\r\n enc1 = chr1 >> 2;\r\n enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);\r\n enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);\r\n enc4 = chr3 & 63;\r\n\r\n if (isNaN(chr2)) {\r\n enc3 = enc4 = 64;\r\n } else if (isNaN(chr3)) {\r\n enc4 = 64;\r\n }\r\n\r\n output = output +\r\n this.keyStr.charAt(enc1) +\r\n this.keyStr.charAt(enc2) +\r\n this.keyStr.charAt(enc3) +\r\n this.keyStr.charAt(enc4);\r\n chr1 = chr2 = chr3 = \"\";\r\n enc1 = enc2 = enc3 = enc4 = \"\";\r\n } while (i < input.length);\r\n\r\n return output;\r\n }\r\n\r\n public decode(input: string): string {\r\n let output = \"\";\r\n let chr1;\r\n let chr2;\r\n let chr3;\r\n let enc1;\r\n let enc2;\r\n let enc3;\r\n let enc4;\r\n let i = 0;\r\n\r\n input = input.replace(\"/[^A-Za-z0-9\\+\\/\\=]/g\", \"\");\r\n\r\n while (i < input.length) {\r\n\r\n enc1 = this.keyStr.indexOf(input.charAt(i++));\r\n enc2 = this.keyStr.indexOf(input.charAt(i++));\r\n enc3 = this.keyStr.indexOf(input.charAt(i++));\r\n enc4 = this.keyStr.indexOf(input.charAt(i++));\r\n\r\n chr1 = (enc1 << 2) | (enc2 >> 4);\r\n chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);\r\n chr3 = ((enc3 & 3) << 6) | enc4;\r\n\r\n output = output + String.fromCharCode(chr1);\r\n\r\n if (enc3 != 64) {\r\n output = output + String.fromCharCode(chr2);\r\n }\r\n if (enc4 != 64) {\r\n output = output + String.fromCharCode(chr3);\r\n }\r\n\r\n }\r\n\r\n return output;\r\n\r\n }\r\n}\r\n","import { NgService } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { eClusterEnv, IRootScope } from \"@models\";\r\nimport { StorageService } from \"./storage.service\";\r\n\r\n\r\n@NgService({\r\n token: Token.BundleLoaderService,\r\n dependencies: [\r\n Token.$RootScope,\r\n Token.$OcLazyLoad,\r\n Token.StorageService\r\n ]\r\n})\r\nexport class BundleLoaderService {\r\n constructor(\r\n private $rootScope: IRootScope,\r\n private $ocLazyLoad: oc.ILazyLoad,\r\n private storageService: StorageService\r\n ) {\r\n\r\n }\r\n\r\n public cachebuster(url: string, minifyIfNotDebug: boolean) {\r\n if (minifyIfNotDebug && this.$rootScope.clusterEnv != eClusterEnv.dev && !this.$rootScope.context.debug) {\r\n let index = url.lastIndexOf(\".\");\r\n url = url.slice(0, index) + \".min\" + url.slice(index);\r\n }\r\n return `${url}?v=${this.$rootScope.cacheBuster}`;\r\n }\r\n\r\n protected getBundleUrl(relativePath: string, minifyIfNotDebug) {\r\n let url = this.storageService.getFileUrl(relativePath);\r\n return this.cachebuster(url, minifyIfNotDebug);\r\n }\r\n\r\n private _libs: { [key: string]: (string | oc.ITypedModuleConfig | oc.IModuleConfig)[] } = {\r\n [Token.SnapLib.key]: [\r\n {\r\n files: [\r\n this.getBundleUrl(\"snap.css\", true),\r\n this.getBundleUrl(`loc/loc-snap.${this.$rootScope.clientLanguage}.js`, false)\r\n ]\r\n },\r\n {\r\n files: [\r\n this.getBundleUrl(`snap.js`, true), \r\n this.getBundleUrl(`kbsnap.js`, true),\r\n ],\r\n serie: true\r\n } \r\n ],\r\n [Token.HandsontableLib.key]: [\r\n this.getBundleUrl(\"lib/handsontable.full.min.js\", false),\r\n this.getBundleUrl(\"lib/handsontable.full.min.css\", false)\r\n ],\r\n [Token.HighchartsLib.key]: [\r\n this.getBundleUrl(\"lib/highcharts.js\", false)\r\n ],\r\n [Token.MonacoLoaderLib.key]: [\r\n this.getBundleUrl(\"lib/monaco-editor/min/vs/loader.js\", false)\r\n ],\r\n [Token.AdminLib.key]: [\r\n {\r\n files: [\r\n this.getBundleUrl(\"admin.js\", true),\r\n this.getBundleUrl(\"admin-templates.js\", false),\r\n this.getBundleUrl(`loc/loc-admin.${this.$rootScope.clientLanguage}.js`, false)\r\n ],\r\n serie: true\r\n }\r\n ],\r\n [Token.Recaptcha.key]: [\r\n {\r\n files: [\r\n \"https://www.google.com/recaptcha/api.js?render=\" + this.$rootScope.recaptchaToken\r\n ],\r\n serie: true\r\n }\r\n ],\r\n [Token.Viewer.key]: [\r\n this.getBundleUrl(\"viewer.js\", true)\r\n ],\r\n [Token.Creator.key]: [\r\n this.getBundleUrl(\"creator.js\", true)\r\n ]\r\n };\r\n\r\n public load(libraries: Token[], paralell = true) {\r\n let urls: (string | oc.ITypedModuleConfig | oc.IModuleConfig)[] = [];\r\n libraries.forEach(lib => urls.pushArray(this._libs[lib.key]));\r\n return this.$ocLazyLoad.load(urls, { serie: !paralell });\r\n }\r\n}\r\n","import { NgService } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { IRootScope } from \"@models\";\r\nimport { StateService, TransitionService } from \"@uirouter/core\";\r\nimport { DialogService } from \"@app/services/dialog.service\";\r\nimport { DrawerService } from \"@app/services/drawer.service\";\r\nimport { SignalrService } from \"@app/services/signalr.service\";\r\nimport { ApiService } from \"@app/services/api.service\";\r\nimport { AuthService } from \"@app/services/auth.service\";\r\nimport { IPromiseTracker } from \"angular\";\r\nimport { KbService } from \"@app/services/kb.service\";\r\n\r\n/**\r\n * Acts as an aggregate service so consolidate dependencies used\r\n * across the crudController inherited classes\r\n */\r\n@NgService({\r\n token: Token.CrudService,\r\n dependencies: [\r\n Token.$Http,\r\n Token.$StateParams,\r\n Token.$RootScope,\r\n Token.$State,\r\n Token.$Window,\r\n Token.DialogService,\r\n Token.DrawerService,\r\n Token.$Q,\r\n Token.SignalRService,\r\n Token.ApiService,\r\n Token.$Transitions,\r\n Token.AuthService,\r\n Token.$Location,\r\n Token.$Timeout,\r\n Token.PromiseTracker,\r\n Token.KbService\r\n ]\r\n})\r\nexport class CrudService {\r\n constructor(\r\n public $http: ng.IHttpService,\r\n public $stateParams: any,\r\n public $rootScope: IRootScope,\r\n public $state: StateService,\r\n public $window: ng.IWindowService,\r\n public dialogService: DialogService,\r\n public drawerService: DrawerService,\r\n public $q: ng.IQService,\r\n public signalrService: SignalrService,\r\n public api: ApiService,\r\n public $transitions: TransitionService,\r\n public authService: AuthService,\r\n public $location: ng.ILocationService,\r\n public $timeout: ng.ITimeoutService,\r\n public promiseTracker: IPromiseTracker,\r\n public kbService: KbService\r\n ) {\r\n\r\n }\r\n}\r\n","import { NgService } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { ApiService } from \"@app/services/api.service\";\r\nimport { DialogButton, DialogButtonArgs, eAlertType, eInputDialogType, eMediaFilter, IAlert, IDialog, IDialogButton, IDialogOptions, IDialogService, IInputOptions, IMediaDialogOptions, IMediaObject, InputDialogButtonArgs, IRootScope, MediaDialogButtonArgs } from \"@models\";\r\nimport { extensions, icons } from \"@tools\";\r\nimport * as angular from \"angular\";\r\n\r\n\r\n@NgService({\r\n token: Token.DialogService,\r\n dependencies: [\r\n Token.$RootScope,\r\n Token.$Compile,\r\n Token.$Timeout,\r\n Token.$Sanitize,\r\n Token.PromiseTracker,\r\n Token.ApiService,\r\n ]\r\n})\r\nexport class DialogService implements IDialogService {\r\n constructor(\r\n private $rootScope: IRootScope,\r\n private $compile: ng.ICompileService,\r\n private $timeout: ng.ITimeoutService,\r\n private $sanitize: ng.sanitize.ISanitizeService,\r\n private promiseTracker: ng.IPromiseTracker,\r\n private api: ApiService\r\n ) {\r\n\r\n this.alerts = [];\r\n this.dialogs = [];\r\n }\r\n\r\n public alerts: IAlert[];\r\n public dialogs: IDialog[];\r\n\r\n public progress(options: IAlert) {\r\n if (!this.alerts) this.alerts = [];\r\n this.alerts.push(options);\r\n }\r\n\r\n public confirm(confirmMessage: string, yesCallback: () => void, noCallback?: () => void) {\r\n this.dialog({\r\n content: confirmMessage,\r\n buttons: [\r\n new DialogButton(loc.ok, icons.success, yesCallback),\r\n new DialogButton(loc.cancel, icons.cancel, noCallback)\r\n ]\r\n });\r\n }\r\n\r\n public alert(alert: IAlert) {\r\n if (!this.alerts) this.alerts = [];\r\n\r\n // handle the alert\r\n // build up the content (lives in msg div)\r\n if (alert.templateUrl || alert.template) {\r\n if (alert.templateUrl) {\r\n // if they provided a templateUrl, we'll use an ng-include to fetch it\r\n alert.msg = $(`
Loading...
`);\r\n } else if (alert.template) {\r\n alert.msg = $(`
${alert.template}
`);\r\n } \r\n // build a scope that we'll use to compile the content\r\n alert.scope = alert.scope || this.$rootScope.$new();\r\n // now compile the dialog with the scope\r\n this.$compile(alert.msg)(alert.scope);\r\n }\r\n // recommended way to handle digest to avoid async digest collisions\r\n this.$timeout(() => {\r\n this.alerts.push(alert);\r\n });\r\n \r\n // $apply scope to ensure first value of array is applied to ui\r\n //this.$rootScope.$apply(); -- caused digest collisions when digest in progress\r\n\r\n let timeShown = alert.timeShown || 5000;\r\n\r\n if (alert.promise) {\r\n (alert as any).inProgress = true;\r\n alert.promise.then(() => {\r\n alert.type = eAlertType.success;\r\n if (alert.successMsg) {\r\n alert.msg = alert.successMsg;\r\n }\r\n }, reason => {\r\n alert.type = eAlertType.error;\r\n if (!angular.isDefined(alert.showPromiseReasonOnFail) || alert.showPromiseReasonOnFail) {\r\n alert.msg = reason;\r\n } \r\n }).finally(() => {\r\n (alert as any).inProgress = false;\r\n\r\n if (!alert.persist) {\r\n this.$timeout(() => {\r\n this.alerts.remove(alert);\r\n if (alert.scope) alert.scope.$destroy();\r\n }, timeShown);\r\n }\r\n });\r\n } else if (!alert.persist) {\r\n this.$timeout(() => {\r\n this.alerts.remove(alert);\r\n if (alert.scope) alert.scope.$destroy();\r\n }, timeShown);\r\n }\r\n\r\n return alert;\r\n }\r\n\r\n public closeAlert(index) {\r\n this.alerts.splice(index, 1);\r\n }\r\n\r\n public dialog(options: IDialogOptions) {\r\n let defaultOptions: IDialogOptions = {\r\n type: eAlertType.info,\r\n content: $(\"
\"),\r\n templateUrl: null,\r\n template: null,\r\n buttons: [],\r\n buttonArgs: () => new DialogButtonArgs(),\r\n scope: null\r\n };\r\n\r\n options = angular.extend({}, defaultOptions, options);\r\n\r\n // build up the content (lives in msg div)\r\n if (options.templateUrl) {\r\n // if they provided a templateUrl, we'll use an ng-include to fetch it\r\n options.content = $(`
Loading...
`);\r\n } else if (options.template) {\r\n options.content = $(options.template);\r\n } else if (angular.isString(options.content)) {\r\n options.content = $(\"\" + this.$sanitize(options.content) + \"\");\r\n }\r\n\r\n // build a dialog object and add it to root scope\r\n let kbDialog: IDialog = {\r\n content: options.content,\r\n buttons: options.buttons,\r\n type: eAlertType[options.type],\r\n visible: false,\r\n keypress: e => {\r\n if (kbDialog.buttons && kbDialog.buttons.length) {\r\n if (e.which == 13) {\r\n (kbDialog.buttons[0] as any).click();\r\n } else if (e.which == 27) { // escape\r\n (kbDialog.buttons.last() as any).click();\r\n }\r\n }\r\n },\r\n tracker: options.tracker,\r\n fullHeight: options.fullHeight\r\n };\r\n\r\n // set up a click command on each button that will call the callback with the args\r\n $.each(kbDialog.buttons, (index, button: IDialogButton) => {\r\n (button as any).click = () => {\r\n let args = options.buttonArgs();\r\n if (button.callback) {\r\n button.callback(args);\r\n }\r\n if (args.close) {\r\n kbDialog.visible = false;\r\n // give time for animation to finish before removing\r\n this.$timeout(() => {\r\n this.dialogs.remove(kbDialog);\r\n if (scope) scope.$destroy();\r\n }, 200);\r\n }\r\n };\r\n });\r\n\r\n // build a scope that we'll use to compile the content\r\n let scope = options.scope || this.$rootScope.$new();\r\n // now compile the dialog with the scope\r\n this.$compile(kbDialog.content)(scope);\r\n\r\n // add the dialog to the rootscope\r\n if (!this.dialogs) this.dialogs = [];\r\n this.dialogs.push(kbDialog);\r\n\r\n // wait for shield animation\r\n this.$timeout(() => {\r\n this.$timeout(() => {\r\n kbDialog.visible = true;\r\n }, 10);\r\n }, 10);\r\n\r\n return kbDialog;\r\n }\r\n \r\n public input(options: IInputOptions) {\r\n\r\n let defaultOptions: IInputOptions = {\r\n msg: \"\",\r\n value: \"\",\r\n inputType: eInputDialogType.text,\r\n buttons: null,\r\n source: null,\r\n labelField: \"\",\r\n valueField: \"\"\r\n };\r\n options = angular.extend({}, defaultOptions, options);\r\n\r\n let scope: any = this.$rootScope.$new();\r\n scope.msg = options.msg;\r\n scope.value = options.value;\r\n scope.source = options.source;\r\n scope.labelField = options.labelField;\r\n scope.valueField = options.valueField;\r\n\r\n let input = \"\";\r\n switch (options.inputType) {\r\n case eInputDialogType.text:\r\n input = \"\";\r\n break;\r\n case eInputDialogType.html:\r\n\r\n break;\r\n case eInputDialogType.textArea:\r\n input = \"\";\r\n break;\r\n case eInputDialogType.select:\r\n input = \"\" +\r\n \" {{item\" + (scope.labelField ? \".\" + scope.labelField : \"\") + \"}}\" +\r\n \" \";\r\n break;\r\n }\r\n\r\n let dialogOptions: IDialogOptions = {\r\n type: eAlertType.info,\r\n content: $(\r\n \"
{{msg}}
\" +\r\n \"
\" +\r\n input +\r\n \"
\"),\r\n templateUrl: null,\r\n buttons: options.buttons,\r\n buttonArgs: () => {\r\n let args = new InputDialogButtonArgs();\r\n args.value = scope.value;\r\n return args;\r\n },\r\n scope\r\n };\r\n\r\n return this.dialog(dialogOptions);\r\n }\r\n\r\n public mediaSelect(options) {\r\n let defaultOptions: IMediaDialogOptions = {\r\n startPath: \"\",\r\n buttons: null,\r\n filter: eMediaFilter.imagesAndVideos,\r\n apiPath: \"api/media\",\r\n rootDir: \"media\",\r\n open: (file: IMediaObject) => {\r\n window.open(file.id, \"_blank\");\r\n }\r\n };\r\n options = angular.extend({}, defaultOptions, options);\r\n let filter = \"\";\r\n\r\n switch (options.filter) {\r\n case eMediaFilter.images:\r\n filter = extensions.image;\r\n break;\r\n case eMediaFilter.videos:\r\n filter = extensions.video;\r\n break;\r\n case eMediaFilter.imagesAndVideos:\r\n filter = extensions.image + \",\" + extensions.video;\r\n break;\r\n case eMediaFilter.environments:\r\n filter = extensions.environments;\r\n break;\r\n }\r\n\r\n let scope: any = this.$rootScope.$new();\r\n scope.dStartPath = options.startPath;\r\n scope.tracker = this.promiseTracker();\r\n let apiPath = \"api/media\";\r\n if (options.apiPath) apiPath = options.apiPath;\r\n let rootDir = \"media\";\r\n if (options.rootDir) rootDir = options.rootDir;\r\n\r\n let dialogOptions: IDialogOptions = {\r\n type: eAlertType.info,\r\n content: $(\r\n '' +\r\n \"\"\r\n ),\r\n templateUrl: null,\r\n buttons: options.buttons,\r\n buttonArgs: () => {\r\n let args = new MediaDialogButtonArgs();\r\n if (scope.dSelected) {\r\n args.selectedItem = scope.dSelected;\r\n }\r\n return args;\r\n },\r\n scope,\r\n tracker: scope.tracker\r\n };\r\n\r\n return this.dialog(dialogOptions);\r\n }\r\n \r\n}\r\n","import { NgService } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { KbService } from \"@app/services/kb.service\";\r\nimport { IRootScope } from \"@models\";\r\nimport { StateDeclaration, Transition, TransitionService } from \"@uirouter/angularjs\";\r\nimport * as angular from \"angular\";\r\n\r\nexport interface IDrawer {\r\n icon?: string;\r\n label?: string;\r\n command?: () => any;\r\n /** an optional function to read whether the drawer is visible or not */\r\n visible?: boolean;\r\n disabled?: boolean;\r\n /** custom content */\r\n content?: JQuery;\r\n children?: IDrawer[];\r\n /** starts a new button group to put space between it and the button to the left of it (used in kbSfdcHeader) */\r\n startGroup?: boolean;\r\n /** ends a button group (used in kbSfdcHeader) */\r\n endGroup?: boolean;\r\n /** custom classes to put on the drawer element */\r\n classes?: string;\r\n /** for drawers that act like toggle buttons */\r\n selected?: boolean;\r\n}\r\n\r\n@NgService({\r\n token: Token.DrawerService,\r\n dependencies: [\r\n Token.$RootScope,\r\n Token.KbService,\r\n Token.$Transitions\r\n ]\r\n})\r\nexport class DrawerService {\r\n constructor(\r\n private $rootScope: IRootScope,\r\n private kbService: KbService,\r\n private $transitions: TransitionService\r\n ) {\r\n this.drawers = [];\r\n this.showHelp = true;\r\n\r\n $transitions.onEnter({}, (transition: Transition, state: StateDeclaration) => {\r\n if (state.name) {\r\n // clear out drawer\r\n this.drawers.clear();\r\n this.pageTitle = null;\r\n this.pageIcon = null;\r\n this.pageType = null;\r\n this.showHelp = true;\r\n }\r\n });\r\n }\r\n\r\n public drawers: IDrawer[];\r\n public helpUrl: string;\r\n public showHelp: boolean;\r\n public pageTitle: string;\r\n public pageIcon: string;\r\n public pageType: string;\r\n\r\n public setHelpUrl(url: string) {\r\n if (!url) url = \"KBMax+CPQ\";\r\n this.helpUrl = \"https://cpqhelp.link/\" + url.toLowerCase();\r\n }\r\n \r\n public addDrawer(icon: string, label: string, command: any, visible?: boolean, children?: IDrawer[]): IDrawer {\r\n if (!angular.isDefined(visible)) {\r\n visible = true;\r\n }\r\n let drawer = {\r\n icon,\r\n label,\r\n command: () => { if (!drawer.disabled) return command() },\r\n visible,\r\n disabled: false,\r\n children\r\n };\r\n\r\n this.drawers.push(drawer);\r\n\r\n return drawer;\r\n }\r\n}\r\n","import { ApiService } from \"@app/services/api.service\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { NgService } from \"@app/di/decorators\";\r\nimport { Utils } from \"@tools\";\r\n\r\n@NgService({\r\n token: Token.InteractionService,\r\n dependencies: [\r\n Token.ApiService\r\n ]\r\n})\r\nexport class InteractionService {\r\n constructor(private api: ApiService) {\r\n\r\n }\r\n\r\n public record(idConfigurator: number): ng.IPromise {\r\n let guid = null;\r\n try {\r\n guid = window.localStorage[\"userGuid\"];\r\n if (!guid) {\r\n guid = window.localStorage[\"userGuid\"] = Utils.shortId();\r\n }\r\n }\r\n catch (e) {\r\n guid = Utils.shortId();\r\n }\r\n\r\n return this.api.interactions.insert({\r\n idConfigurator: idConfigurator,\r\n userGuid: guid\r\n });\r\n }\r\n}\r\n","import { NgService } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { AuthService } from \"@app/services/auth.service\";\r\nimport { INameValue, IRootScope } from \"@models\";\r\nimport { icons } from \"@tools\";\r\n\r\n@NgService({\r\n token: Token.KbService,\r\n dependencies: [\r\n Token.$RootScope,\r\n Token.AuthService,\r\n Token.$Q,\r\n Token.$Timeout\r\n ]\r\n})\r\nexport class KbService {\r\n constructor(\r\n private $rootScope: IRootScope,\r\n private authService: AuthService,\r\n private $q: ng.IQService,\r\n private $timeout: ng.ITimeoutService\r\n ) {\r\n\r\n }\r\n\r\n public loc(key: string): string {\r\n if (key) {\r\n const lkey = key.toLowerCase();\r\n if (loc[lkey]) {\r\n return loc[lkey];\r\n }\r\n }\r\n return key;\r\n }\r\n\r\n public icon(key: string): string {\r\n let icon = icons[key];\r\n if (!icon) {\r\n icon = key;\r\n }\r\n\r\n return icon;\r\n }\r\n\r\n public getExtension(path: string): string {\r\n if (!path) { return \"\"; }\r\n\r\n return path.split(\".\").pop().toLowerCase();\r\n }\r\n\r\n /**\r\n * given a kb enum type, gives back an array of NameValue objects\r\n * with localized names that can be used in a kbSelect\r\n *\r\n */\r\n public getEnumSelects(enm: any, enumName: string): INameValue[] {\r\n const selects: INameValue[] = [];\r\n for (const name in enm) {\r\n const locName = enumName + \"_\" + name + \"_title\";\r\n const locValue = this.loc(locName);\r\n\r\n selects.push({\r\n name: locValue,\r\n value: enm[name]\r\n });\r\n }\r\n return selects;\r\n }\r\n\r\n public fxConvert = (val, to, from = null) => {\r\n if (!from) from = this.$rootScope.companySettings.currency.toUpperCase();\r\n return fx(val).from(from).to(to.toUpperCase());\r\n }\r\n\r\n public copyDataToClipboard(data?: string) {\r\n\r\n const $el = jQuery('

Copy the Json below and use \\'Paste Json\\' in another location.

');\r\n const $textarea = jQuery('');\r\n jQuery(\"body\").find(\".copyPopup\").remove();\r\n $el.append($textarea);\r\n this.$timeout(() => {\r\n const textarea: HTMLTextAreaElement = $textarea.get(0) as HTMLTextAreaElement;\r\n $textarea.val(data);\r\n $textarea.focus();\r\n textarea.setSelectionRange(0, 999999);\r\n textarea.addEventListener(\"keydown\", (ev) => {\r\n if (ev.key == \"c\" && ev.ctrlKey) {\r\n this.$timeout(() => {\r\n $el.remove();\r\n }, 1);\r\n }\r\n if (ev.key == \"Escape\") {\r\n this.$timeout(function () {\r\n $el.remove();\r\n }, 1);\r\n }\r\n });\r\n }, 1);\r\n jQuery(\"body\").append($el);\r\n }\r\n\r\n public pasteClipboardData(): ng.IPromise {\r\n\r\n const defer = this.$q.defer();\r\n jQuery(\"body\").find(\".copyPopup\").remove();\r\n\r\n const $el = jQuery('

Paste the Json below.

');\r\n const $textarea = jQuery('');\r\n $el.append($textarea);\r\n jQuery(\"body\").append($el);\r\n this.$timeout(() => {\r\n const textarea: HTMLTextAreaElement = $textarea.get(0) as HTMLTextAreaElement;\r\n $textarea.focus();\r\n textarea.setSelectionRange(0, 999999);\r\n textarea.addEventListener(\"keydown\", (ev) => {\r\n if (ev.key == \"v\" && ev.ctrlKey) {\r\n this.$timeout(() => {\r\n defer.resolve($textarea.val() as string);\r\n $el.remove();\r\n }, 1);\r\n }\r\n if (ev.key == \"Escape\") {\r\n this.$timeout(function () {\r\n $el.remove();\r\n }, 1);\r\n }\r\n });\r\n }, 1);\r\n\r\n return defer.promise;\r\n }\r\n\r\n public fxConvertAsync(val: number, to: string): ng.IPromise {\r\n const deferred = this.$q.defer();\r\n deferred.resolve(this.fxConvert(val, to));\r\n return deferred.promise;\r\n }\r\n\r\n public fly = (sourceSelector: string, targetSelector: string, callback?: () => void) => {\r\n const $source = $(sourceSelector).eq(0);\r\n const $target = $(targetSelector).eq(0);\r\n\r\n if ($source) {\r\n const $fly = $source.clone()\r\n .offset({\r\n top: $source.offset().top,\r\n left: $source.offset().left\r\n })\r\n .css({\r\n \"opacity\": \"0.5\",\r\n \"position\": \"fixed\",\r\n \"height\": $source.height(),\r\n \"width\": $source.width(),\r\n \"z-index\": \"1000\"\r\n })\r\n .appendTo($(\"body\"))\r\n .animate({\r\n top: $target.offset().top,\r\n left: $target.offset().left,\r\n width: $target.width(),\r\n height: $target.height()\r\n }, 800, \"easeInOutSine\", () => {\r\n $fly.remove();\r\n if (callback) callback();\r\n $target.effect(\"bounce\", { distance: 10, times: 5 }, 500);\r\n });\r\n }\r\n\r\n }\r\n}\r\n","import { NgService } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { ApiService } from \"@app/services/api.service\";\r\nimport { AuthService } from \"@app/services/auth.service\";\r\nimport { DialogService } from \"@app/services/dialog.service\";\r\nimport { KbService } from \"@app/services/kb.service\";\r\nimport { eWorkflowAction, IConfiguredProduct, IQuote, IQuoteProduct, IRootScope } from \"@models\";\r\nimport { StateService } from \"@uirouter/angularjs\";\r\n\r\nexport interface IAddProductArgs {\r\n idProduct?: number;\r\n qty?: number;\r\n configuredProduct?: IConfiguredProduct;\r\n addLocally?: boolean;\r\n silent?: boolean; // whether to suppress dialogs\r\n /**\r\n * When adding a product ends up creating a new quote, the product\r\n * can determine the quote currency.\r\n */\r\n currency ?: string;\r\n}\r\n\r\n@NgService({\r\n token: Token.QuoteService,\r\n dependencies: [\r\n Token.$RootScope,\r\n Token.$Q,\r\n Token.KbService,\r\n Token.$Http,\r\n Token.$State,\r\n Token.$CookieStore,\r\n Token.DialogService,\r\n Token.ApiService,\r\n ]\r\n})\r\nexport class QuoteService {\r\n \r\n constructor(\r\n private $rootScope: IRootScope,\r\n private $q: ng.IQService,\r\n private kbService: KbService,\r\n private $http: ng.IHttpService,\r\n private $state: StateService,\r\n private $cookieStore: ng.cookies.ICookieStoreService,\r\n private dialogService: DialogService,\r\n private api: ApiService\r\n ) {\r\n\r\n let quoteIdFromCookie: any;\r\n try {\r\n quoteIdFromCookie = this.getActiveQuoteData();\r\n } catch (e) {\r\n }\r\n if (quoteIdFromCookie && quoteIdFromCookie.guidToken) {\r\n $http.get(\"/api/quotes/guid/\" + quoteIdFromCookie.guidToken, {\r\n ignoreSecurity: true,\r\n ignoreErrors: true\r\n }).then(r => {\r\n if (r.data.ownedBy == $rootScope.user.id ||\r\n r.data.allowedActions.some(a => a.type == eWorkflowAction.modifyProducts)\r\n ) {\r\n this.quote = r.data;\r\n } else {\r\n // tslint:disable-next-line:no-console\r\n console.log(\r\n \"Active Quote with ID \" +\r\n quoteIdFromCookie.guidToken +\r\n \" does not have proper add product permissions. Unsetting cookie.\"\r\n );\r\n this.$cookieStore.remove(QuoteService.COOKIE_NAME);\r\n }\r\n }, () => {\r\n // tslint:disable-next-line:no-console\r\n console.log(\"Active Quote with ID \" +\r\n quoteIdFromCookie.guidToken +\r\n \" does not exist. Unsetting cookie.\");\r\n this.$cookieStore.remove(QuoteService.COOKIE_NAME);\r\n });\r\n }\r\n }\r\n\r\n public static COOKIE_NAME: string = \"activeQuote\";\r\n\r\n private _quote: IQuote;\r\n public get quote() {\r\n return this._quote;\r\n }\r\n public set quote(val: IQuote) {\r\n this._quote = val;\r\n\r\n // set the active quote in a cookie\r\n if (val) {\r\n this.storeCookie(val);\r\n } else {\r\n this.$cookieStore.remove(QuoteService.COOKIE_NAME);\r\n }\r\n }\r\n\r\n public storeCookie(quote: IQuote) {\r\n this.$cookieStore.put(QuoteService.COOKIE_NAME, JSON.stringify({\r\n idQuote: quote.id,\r\n guidToken: quote.guidToken\r\n }));\r\n }\r\n\r\n public getActiveQuoteData() {\r\n let cookie = this.$cookieStore.get(QuoteService.COOKIE_NAME);\r\n if (!cookie) return null;\r\n return JSON.parse(cookie);\r\n }\r\n\r\n public getLatestQuoteProduct(quote: IQuote): IQuoteProduct {\r\n let result: IQuoteProduct = null;\r\n\r\n quote.products.forEach(p => {\r\n if (!result) result = p;\r\n else {\r\n if (result.id < p.id) {\r\n result = p;\r\n }\r\n }\r\n });\r\n\r\n return result;\r\n }\r\n\r\n public addProduct(args: IAddProductArgs): ng.IPromise {\r\n let deferred = this.$q.defer();\r\n // if there is no current quote, then we need to create one,\r\n // add the quoteProduct to it, and save on the server\r\n if (!this.quote) {\r\n this.quote = this.getNewQuote();\r\n if (args.currency) this.quote.currency = args.currency;\r\n \r\n // add just the id of the product to the quote products array\r\n this.quote.products.push({\r\n idProduct: args.idProduct,\r\n qty: args.qty,\r\n configuredProduct: args.configuredProduct,\r\n isConfigured: (args.configuredProduct !== null && args.configuredProduct !== undefined)\r\n });\r\n\r\n // save it\r\n this.api.quotes.save(this.quote, this.$rootScope.contentTracker).then(r => {\r\n this.quote = r;\r\n \r\n deferred.resolve(this.getLatestQuoteProduct(r));\r\n });\r\n } else { // there is an active quote\r\n if (this.quote.idWorkflow &&\r\n !this.quote.allowedActions.some(a => a.type == eWorkflowAction.modifyProducts)\r\n ) {\r\n let confirm = () => {\r\n this.quote = null;\r\n this.addProduct(args).then((r) => {\r\n deferred.resolve(this.getLatestQuoteProduct(r));\r\n });\r\n };\r\n if (args.silent) {\r\n confirm();\r\n } else {\r\n this.dialogService.confirm(\"You cannot add products to quote '\" +\r\n this.quote.name +\r\n \"' at this time. Would you like to add it to a new quote?\",\r\n () => {\r\n confirm();\r\n });\r\n }\r\n \r\n } else {\r\n // first we post to the server... it has it's own logic to figure\r\n // out duplicates and quantities\r\n let newQuoteProduct: IQuoteProduct = {\r\n idProduct: args.idProduct,\r\n qty: args.qty,\r\n configuredProduct: args.configuredProduct,\r\n isConfigured: (args.configuredProduct !== null && args.configuredProduct !== undefined)\r\n };\r\n\r\n this.api.quotes.insertQuoteProduct(\r\n this.quote.id,\r\n newQuoteProduct,\r\n this.$rootScope.contentTracker\r\n ).then(r => {\r\n this.quote = r;\r\n deferred.resolve(this.getLatestQuoteProduct(r));\r\n });\r\n\r\n // now we figure it out locally to get an immediate update\r\n let existingProduct = this.quote.products.find(qp =>\r\n !newQuoteProduct.isConfigured && qp.idProduct == newQuoteProduct.idProduct);\r\n\r\n if (args.addLocally) {\r\n if (!existingProduct) {\r\n this.quote.products.push(newQuoteProduct);\r\n } else {\r\n existingProduct.qty += args.qty;\r\n }\r\n }\r\n }\r\n }\r\n return deferred.promise;\r\n }\r\n\r\n public canModifyProductsOfQuote(q: IQuote): boolean {\r\n return !q.idWorkflow || q.allowedActions.some(a => a.type == eWorkflowAction.modifyProducts);\r\n }\r\n\r\n public copyProductToActiveQuote(idQuoteProduct: number): ng.IPromise {\r\n let deferred = this.$q.defer();\r\n\r\n if (this.canModifyProductsOfQuote(this.quote)) {\r\n this.api.quotes.copyQuoteProduct(\r\n this.quote.id,\r\n idQuoteProduct,\r\n this.$rootScope.contentTracker\r\n ).then(r => {\r\n this.quote = r;\r\n deferred.resolve();\r\n });\r\n } else {\r\n this.dialogService.confirm(\r\n \"You cannot add products to quote '\" +\r\n this.quote.name +\r\n \"' at this time. Would you like to add it to a new quote?\",\r\n () => {\r\n this.quote = null;\r\n this.copyProductToNewQuote(idQuoteProduct).then(() => {\r\n deferred.resolve();\r\n });\r\n });\r\n }\r\n return deferred.promise;\r\n }\r\n\r\n public copyProductToNewQuote(idQuoteProduct: number): ng.IPromise {\r\n this.quote = this.getNewQuote();\r\n\r\n // save it\r\n return this.api.quotes.save(this.quote, this.$rootScope.contentTracker).then(r => {\r\n this.quote = r;\r\n return this.api.quotes.copyQuoteProduct(\r\n this.quote.id,\r\n idQuoteProduct,\r\n this.$rootScope.contentTracker\r\n ).then(r => {\r\n this.quote = r;\r\n });\r\n });\r\n }\r\n\r\n \r\n\r\n public goToQuote() {\r\n if (this.quote) {\r\n this.$state.go(\"kb.quoteEdit\", { id: this.quote.id });\r\n } else {\r\n this.$state.go(\"kb.quoteNew\");\r\n }\r\n }\r\n public getNewQuote(): IQuote {\r\n return {\r\n name: loc.newquote,\r\n createdBy: this.$rootScope.user.id,\r\n ownedBy: this.$rootScope.user.id,\r\n currency: this.$rootScope.companySettings.currency,\r\n quoteProducts: [],\r\n products: [],\r\n discountPercentage: 0\r\n } as IQuote;\r\n }\r\n public getQuoteById(id: number): ng.IPromise {\r\n let promise: ng.IPromise;\r\n\r\n if (this.$rootScope.user.id != AuthService.ANONYMOUS_USER_ID) {\r\n promise = this.$http.get(\r\n \"/api/quotes/\" + id,\r\n { method: \"GET\", tracker: this.$rootScope.contentTracker } as ng.IRequestConfig);\r\n } else {\r\n let data = this.getActiveQuoteData();\r\n if (data && data.idQuote == id) {\r\n promise = this.$http.get(\r\n \"/api/quotes/guid/\" + data.guidToken,\r\n { method: \"GET\", tracker: this.$rootScope.contentTracker } as ng.IRequestConfig);\r\n } else {\r\n promise = this.$http.get(\r\n \"/api/quotes/\" + id,\r\n { method: \"GET\", tracker: this.$rootScope.contentTracker } as ng.IRequestConfig);\r\n }\r\n }\r\n return promise.then(data => {\r\n return (data ? data.data : null);\r\n });\r\n }\r\n\r\n}\r\n","import { NgService } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { AsyncRuleFunction, Configurator, CToken, eRuleType, IJsResult, MasterRuleFunction, RuleContainer, SyncRuleFunction, SvgViewer } from \"@models\";\r\nimport { KPromise } from \"@rules\";\r\nimport { Logger } from \"@tools\";\r\nimport * as Q from \"q\";\r\n\r\n\r\nexport interface IRuleService {\r\n runRuleTypeAsync(\r\n config: Configurator,\r\n ruleType: string,\r\n args: T\r\n ): ng.IPromise>;\r\n}\r\n\r\n@NgService({\r\n token: Token.RuleService,\r\n dependencies: [\r\n Token.$Q,\r\n ]\r\n})\r\nexport class RuleService implements IRuleService {\r\n constructor(\r\n private $q: ng.IQService\r\n ) {\r\n\r\n }\r\n private _masterRuleCache: { [hash: string]: MasterRuleFunction } = {};\r\n\r\n public getConfiguratorHash(config: Configurator) {\r\n return `${config.idProduct || 0}-${config.idScene || 0}-${config.idQuoteHeader || 0}-${config.id}`;\r\n }\r\n public getRuleName(rc: RuleContainer) {\r\n return `rule-${rc.id}`;\r\n }\r\n public getRuleHeader(rc: RuleContainer) {\r\n let desc = `${rc.ruleType.toSentence()} Rule`;\r\n if (rc.ruleType.equalsAny(eRuleType.field, eRuleType.action, eRuleType.function, eRuleType.optionFilter)) {\r\n desc += \" - \" + rc.name;\r\n }\r\n let stars = \"*\".repeat(Math.max(desc.length - 1, 70));\r\n return `\\r\\n/${stars}\\r\\n * ${desc}\\r\\n ${stars}/\\r\\n`;\r\n }\r\n public getConfiguratorMasterRule(config: Configurator): MasterRuleFunction {\r\n let hash = this.getConfiguratorHash(config);\r\n if (!this._masterRuleCache.hasOwnProperty(hash)) {\r\n let globalRc = config.ruleContainers.find(rc => rc.ruleType.isEqual(eRuleType.global));\r\n let js = globalRc ? globalRc.js + \"\\r\\n\\r\\n\" : \"\";\r\n let globalEventRc = config.ruleContainers.find(rc => rc.ruleType.isEqual(eRuleType.globalEvent));\r\n js += globalEventRc ? globalEventRc.js + \"\\r\\n\\r\\n\" : \"\";\r\n js += \"var _ruleDb = {\\r\\n\";\r\n let ruleContainers = config.ruleContainers\r\n .concat(config.actions)\r\n .concat(config.functions)\r\n .concat(config.getChildrenOfType(CToken.Field, CToken.Button, CToken.SvgViewer, CToken.NestedSet, CToken.RuleContainer))\r\n .concat(config.optionFilters);\r\n config.getChildrenOfType(CToken.SvgViewer).forEach(svg => ruleContainers = ruleContainers.concat(svg.ruleContainers));\r\n config.referencedConfigurators.forEach(refConfig => ruleContainers = ruleContainers.concat(refConfig.ruleContainers));\r\n\r\n ruleContainers.forEach(rc => {\r\n if (rc.ruleType != eRuleType.global && rc.js) {\r\n js += this.getRuleHeader(rc);\r\n js += `\"${this.getRuleName(rc)}\": `;\r\n var ruleJs = \"\\r\\n\\t\" + rc.js.split(\"\\n\").join(\"\\r\\n\\t\")\r\n if (rc.ruleType == eRuleType.optionFilter) {\r\n js += \"function(){\\r\\n\" + ruleJs + \"\\r\\n},\";\r\n } else {\r\n js += \"function(){return Q.fcall(function () {\\r\\n\" + ruleJs + \"\\r\\n})},\";\r\n }\r\n }\r\n });\r\n\r\n js += \"};\\r\\n\\r\\n\";\r\n js += \"return _ruleDb[e.ruleName]();\";\r\n\r\n this._masterRuleCache[hash] = new Function(\"Q\", \"e\", js) as SyncRuleFunction;\r\n }\r\n return this._masterRuleCache[hash];\r\n }\r\n\r\n public compileAsyncRule(js: string): AsyncRuleFunction {\r\n // tab out the code\r\n js = \"\\t\\t\" + js.split(\"\\n\").join(\"\\r\\n\\t\\t\");\r\n\r\n // wrap the js. We use Q.when().then(code) to make sure that errors are propogated to our promise error handler\r\n let rule = \"\\t\" + \"return Q.fcall(function () {\\n\" +\r\n js + \"\\n\" +\r\n \"\\t})\\n\";\r\n\r\n return new Function(\"Q\", \"e\", rule) as AsyncRuleFunction;\r\n }\r\n\r\n public runRuleAsync(parameters, fn: MasterRuleFunction): ng.IPromise> {\r\n let promise = (fn(Q, parameters) as ng.IPromise)\r\n .then(() => {\r\n return {\r\n parameters,\r\n hasError: false,\r\n error: null\r\n } as IJsResult\r\n }, error => {\r\n return {\r\n parameters,\r\n hasError: true,\r\n error\r\n } as IJsResult;\r\n });\r\n\r\n return promise;\r\n }\r\n\r\n public runJsAsync(parameters: T, js: string): ng.IPromise> {\r\n var fn = this.compileAsyncRule(js);\r\n return this.runRuleAsync(parameters, fn);\r\n }\r\n\r\n\r\n public compileSyncRule(js: string): SyncRuleFunction {\r\n return new Function(\"e\", js) as SyncRuleFunction;\r\n }\r\n\r\n /**\r\n * runs the rule synchronously... Only for use in special circumstances if you know what you're doing!\r\n */\r\n public runRuleSync(parameters: T, fn: MasterRuleFunction): IJsResult {\r\n let result: IJsResult = {};\r\n try {\r\n fn(Q, parameters);\r\n } catch (err) {\r\n result.hasError = true;\r\n result.error = err.message;\r\n }\r\n result.parameters = parameters;\r\n\r\n return result;\r\n }\r\n\r\n public runJsSync(parameters: T, js: string): IJsResult {\r\n let fn = this.compileSyncRule(js);\r\n return this.runRuleSync(parameters, fn);\r\n }\r\n\r\n\r\n /**\r\n * runs the rule of a rule container, compiling and caching it along the way\r\n * @param ruleContainer \r\n * @param args \r\n */\r\n public runRuleContainerAsync(\r\n ruleContainer: RuleContainer,\r\n args: T\r\n ): ng.IPromise> {\r\n if (ruleContainer && ruleContainer.js) {\r\n let masterRule = this.getConfiguratorMasterRule(ruleContainer.$parentConfigurator);\r\n args[\"ruleName\"] = this.getRuleName(ruleContainer);\r\n \r\n let start = Logger.logRuleStart(ruleContainer.$parentConfigurator.name, ruleContainer.ruleType);\r\n let promise = this.runRuleAsync(args, masterRule);\r\n if (Logger.writeRuleCycleLogs) {\r\n promise = promise.then(result => {\r\n Logger.logRuleEnd(ruleContainer.$parentConfigurator.name, ruleContainer.ruleType, start);\r\n return result;\r\n });\r\n }\r\n return promise;\r\n } else { // if there is no text in the rule, then don't bother running it\r\n let result: IJsResult = {\r\n hasError: false,\r\n parameters: args\r\n };\r\n return (new KPromise(result)) as any;\r\n }\r\n }\r\n\r\n public runRuleContainerSync(\r\n ruleContainer: RuleContainer,\r\n args: T\r\n ): IJsResult {\r\n if (ruleContainer && ruleContainer.js) {\r\n let masterRule = this.getConfiguratorMasterRule(ruleContainer.$parentConfigurator);\r\n args[\"ruleName\"] = this.getRuleName(ruleContainer);\r\n return this.runRuleSync(args, masterRule);\r\n } else { // if there is no text in the rule, then don't bother running it\r\n let result: IJsResult = {\r\n hasError: false,\r\n parameters: args\r\n };\r\n return result;\r\n }\r\n }\r\n\r\n // /**\r\n // * runs the rule of a rule container, compiling and caching it along the way\r\n // * @param ruleContainer \r\n // * @param args \r\n // */\r\n // public runRuleContainerAsync(\r\n // ruleContainer: RuleContainer,\r\n // args: T\r\n // ): ng.IPromise> {\r\n // // find the cached fn, if it's already been compiled\r\n // if (ruleContainer && ruleContainer.js) {\r\n // // find or cache the compiled fn for perf\r\n // ruleContainer.$asyncFn = ruleContainer.$asyncFn || this.compileAsyncRule(ruleContainer.$parentConfigurator.getRuleJsFromContainer(ruleContainer));\r\n // return this.runRuleAsync(args, ruleContainer.$asyncFn);\r\n // } else { // if there is no text in the rule, then don't bother running it\r\n // let result: IJsResult = {\r\n // hasError: false,\r\n // parameters: args\r\n // };\r\n // return (new KPromise(result)) as any;\r\n // }\r\n // }\r\n\r\n // public runRuleContainerSync(\r\n // ruleContainer: RuleContainer,\r\n // args: T\r\n // ): IJsResult {\r\n // // find the cached fn, if it's already been compiled\r\n // if (ruleContainer && ruleContainer.js) {\r\n // // find or cache the compiled fn for perf\r\n // ruleContainer.$syncFn = ruleContainer.$syncFn || this.compileSyncRule(ruleContainer.$parentConfigurator.getRuleJsFromContainer(ruleContainer));\r\n // return this.runRuleSync(args, ruleContainer.$syncFn);\r\n // } else { // if there is no text in the rule, then don't bother running it\r\n // let result: IJsResult = {\r\n // hasError: false,\r\n // parameters: args\r\n // };\r\n // return result;\r\n // }\r\n // }\r\n\r\n\r\n public runRuleTypeAsync(\r\n config: Configurator,\r\n ruleType: string,\r\n args: T\r\n ): ng.IPromise> {\r\n let rc = config.ruleContainers.find(rc => {\r\n return rc.ruleType.isEqual(ruleType);\r\n });\r\n return this.runRuleContainerAsync(rc, args);\r\n }\r\n\r\n public runActionRuleByIdAsync(\r\n config: Configurator,\r\n actionId: string,\r\n args: T\r\n ): ng.IPromise> {\r\n let container = config.actions.find(a => a.id == actionId);\r\n\r\n return this.runRuleContainerAsync(container, args);\r\n }\r\n}\r\n","import { NgService } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { ApiService } from \"@app/services/api.service\";\r\nimport { Base64Service } from \"@app/services/base64.service\";\r\nimport { DialogService } from \"@app/services/dialog.service\";\r\nimport { DrawerService } from \"@app/services/drawer.service\";\r\nimport { IRootScope } from \"@models\";\r\nimport { StateService } from \"@uirouter/core\";\r\n\r\n/**\r\n * Acts as an aggregate service so consolidate dependencies used\r\n * across the crudController inherited classes\r\n */\r\n@NgService({\r\n token: Token.SearchService,\r\n dependencies: [\r\n Token.$Location,\r\n Token.$State,\r\n Token.$Http,\r\n Token.$RootScope,\r\n Token.DialogService,\r\n Token.DrawerService,\r\n Token.$Timeout,\r\n Token.$Q,\r\n Token.ApiService,\r\n Token.Base64Service,\r\n Token.$Filter\r\n ]\r\n})\r\nexport class SearchService {\r\n constructor(\r\n public $location: ng.ILocationService,\r\n public $state: StateService,\r\n public $http: ng.IHttpService,\r\n public $rootScope: IRootScope,\r\n public dialogService: DialogService,\r\n public drawerService: DrawerService,\r\n public $timeout: ng.ITimeoutService,\r\n public $q: ng.IQService,\r\n public api: ApiService,\r\n public base64Service: Base64Service,\r\n public $filter: ng.IFilterService\r\n ) {\r\n\r\n }\r\n}\r\n","import { NgService } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\n\r\nexport interface IRetryItem {\r\n retry: () => void;\r\n reason: string;\r\n cancel: () => void;\r\n}\r\n\r\n@NgService({\r\n token: Token.SecurityRetryService,\r\n dependencies: [\r\n Token.$Q,\r\n ]\r\n})\r\nexport class SecurityRetryService {\r\n constructor(\r\n private $q: ng.IQService\r\n ) {\r\n\r\n }\r\n private retryQueue: IRetryItem[] = [];\r\n public onItemAdded: () => void;\r\n\r\n public retryAll() {\r\n while (this.retryQueue.length) {\r\n this.retryQueue.shift().retry();\r\n }\r\n }\r\n\r\n public pushRetryFn(reason, retryFn) {\r\n let deferredRetry = this.$q.defer();\r\n let retryItem: IRetryItem = {\r\n reason,\r\n retry: () => {\r\n this.$q.when(retryFn()).then(value => {\r\n deferredRetry.resolve(value);\r\n }, value => {\r\n deferredRetry.reject(value);\r\n });\r\n },\r\n cancel: () => {\r\n deferredRetry.reject();\r\n }\r\n };\r\n this.push(retryItem);\r\n return deferredRetry.promise as ng.IHttpPromise;\r\n }\r\n \r\n public push(retryItem) {\r\n this.retryQueue.push(retryItem);\r\n if (this.onItemAdded) {\r\n this.onItemAdded();\r\n }\r\n }\r\n\r\n}\r\n","import { NgService } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { DialogService } from \"@app/services/dialog.service\";\r\nimport { eAlertType, IPriceItem, IPriceItemBase, IPriceObject, IQuote, IRootScope, ISfdcCpqGetProductsRequest, ISfdcCpqGetProductsResponse, ISfdcCpqGetProductsResponse_Product2, ISfdcCpqPayload, ISfdcCpqPayloadOption } from \"@models\";\r\nimport { KPromise } from \"@rules\";\r\nimport { IMessage } from \"@tools\";\r\n\r\n@NgService({\r\n token: Token.SfdcService,\r\n dependencies: [\r\n Token.$RootScope,\r\n Token.$Q,\r\n Token.DialogService,\r\n ]\r\n})\r\nexport class SfdcService {\r\n constructor(\r\n private $rootScope: IRootScope,\r\n private $q: ng.IQService,\r\n private dialogService: DialogService\r\n ) {\r\n\r\n }\r\n\r\n /**\r\n * get's the record passed in through the canvas context\r\n */\r\n public record() {\r\n if (this.$rootScope.isSfdc) return this.canvasRequest().context.environment.record;\r\n }\r\n\r\n public canvasRequest() {\r\n if (this.$rootScope.isSfdc) return this.$rootScope.context.sfdcCanvasRequest;\r\n }\r\n\r\n /**\r\n * navigates to the salesforce view page of the object with the given id\r\n */\r\n public navigateToObject(id: string) {\r\n Sfdc.canvas.client.publish(this.$rootScope.context.sfdcCanvasRequest.client, {\r\n name: \"navigateToObject\",\r\n payload: id\r\n });\r\n }\r\n\r\n public toggleFullscreen() {\r\n Sfdc.canvas.client.publish(this.canvasRequest().client, {\r\n name: \"toggleFullscreen\",\r\n payload: {}\r\n });\r\n }\r\n\r\n /**\r\n * send a message to the visual force page hosting our canvas\r\n * @param msg\r\n */\r\n public sendMessage(msg: IMessage) {\r\n if (this.$rootScope.isSfdc) {\r\n Sfdc.canvas.client.publish(this.canvasRequest().client, {\r\n name: msg.name,\r\n payload: msg.data\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * makes a quote the primary quote in sfdc by calling through the canvas \r\n * @param quote\r\n */\r\n public makePrimaryQuote(quote: IQuote): ng.IPromise {\r\n let deferred = this.$q.defer();\r\n\r\n let sr = this.$rootScope.context.sfdcCanvasRequest;\r\n let url = sr.context.links.restUrl + \"sobjects/KBMAX__Quote__c/\" + quote.externalId;\r\n Sfdc.canvas.client.ajax(url, {\r\n client: sr.client,\r\n method: \"PATCH\",\r\n contentType: \"application/json\",\r\n data: JSON.stringify({\r\n KBMAX__Primary__c: true\r\n }),\r\n success: data => {\r\n if (data.status === 204) {\r\n deferred.resolve();\r\n } else {\r\n deferred.reject();\r\n }\r\n }\r\n });\r\n\r\n return deferred.promise;\r\n }\r\n\r\n /**\r\n * when integrating with steelbrick, because of their easyXdm setup, we have to wait for the canvas\r\n * to tell us what the id of the product is.\r\n */\r\n public getPayloadFromSfdcCpq(): ng.IPromise {\r\n let deferred = this.$q.defer();\r\n let sr = this.$rootScope.context.sfdcCanvasRequest;\r\n\r\n Sfdc.canvas.client.subscribe(sr.client, {\r\n name: \"sfdccpq_payload_response\",\r\n onData: (e: ISfdcCpqPayload) => {\r\n deferred.resolve(e);\r\n }\r\n });\r\n\r\n Sfdc.canvas.client.publish(sr.client, {\r\n name: \"sfdccpq_payload_request\",\r\n payload: {}\r\n });\r\n\r\n return deferred.promise;\r\n }\r\n\r\n public getProducts(productCodes: string[]): ng.IPromise {\r\n let deferred = this.$q.defer();\r\n let sr = this.$rootScope.context.sfdcCanvasRequest;\r\n\r\n Sfdc.canvas.client.subscribe(sr.client, {\r\n name: \"sfdccpq_getproducts_response\",\r\n onData: (e: ISfdcCpqGetProductsResponse) => {\r\n deferred.resolve(e.products);\r\n }\r\n });\r\n\r\n Sfdc.canvas.client.publish(sr.client, {\r\n name: \"sfdccpq_getproducts\",\r\n payload: { productCodes } as ISfdcCpqGetProductsRequest\r\n });\r\n\r\n return deferred.promise;\r\n }\r\n\r\n private getColumnOrMetaValue(key: string, priceItem: IPriceItemBase) {\r\n // find the price column if there is one\r\n if (priceItem.columns) {\r\n let colNames = Object.keys(priceItem.columns);\r\n for (let colName of colNames) {\r\n if (colName.isEqual(key)) {\r\n return priceItem.columns[colName];\r\n }\r\n }\r\n }\r\n // find the metadata property if there is one\r\n if (priceItem.metadata) {\r\n let metaNames = Object.keys(priceItem.metadata);\r\n for (let metaName of metaNames) {\r\n if (metaName.isEqual(key)) {\r\n return priceItem.metadata[metaName];\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n protected getConfigurationAttribute(payload: ISfdcCpqPayload, name: string): string {\r\n for (let att in payload.data.product.configurationAttributes) {\r\n if (!att.isEqual(\"attributes\") && att.isEqual(name)) {\r\n return att;\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n protected addColumnsAndMetadataToConfigurationObject(\r\n payload: ISfdcCpqPayload,\r\n configurationData: {},\r\n item: IPriceItem\r\n ) {\r\n for (let col in item.columns) {\r\n let att = this.getConfigurationAttribute(payload, col);\r\n if (att) {\r\n configurationData[att] = item.columns[col];\r\n }\r\n }\r\n for (let m in item.metadata) {\r\n let att = this.getConfigurationAttribute(payload, m);\r\n if (att) {\r\n configurationData[att] = item.metadata[m];\r\n }\r\n }\r\n }\r\n\r\n private dynamicOptionsToQueryStatic: { item: IPriceItem, dynamicOption: ISfdcCpqPayloadOption }[] = [];\r\n protected buildOptions(payload: ISfdcCpqPayload, item: IPriceItem, optionConfig: { [name: string]: ISfdcCpqPayloadOption[]}, isDynamic: boolean = false) {\r\n if (!optionConfig) {\r\n let options: { [name: string]: ISfdcCpqPayloadOption[]};\r\n if (isDynamic)\r\n options = { 'Dynamic Options': [] };\r\n else\r\n options = { 'Other Options': []};\r\n optionConfig = options;\r\n }\r\n\r\n //let dynamicOptionsToQuery: { item: IPriceItem, dynamicOption: ISfdcCpqPayloadOption }[] = [];\r\n if (isDynamic) {\r\n \r\n item.items.forEach((element, index) => {\r\n let salesforceId = item.columns.salesforceId || item.metadata.salesforceId;\r\n let dynamicOption = {\r\n ProductCode: element.sku,\r\n Quantity: element.qty ?? 1,\r\n configurationData: {},\r\n productId: '',\r\n selected: true\r\n }\r\n\r\n this.addColumnsAndMetadataToConfigurationObject(payload, dynamicOption.configurationData, element);\r\n // if (element.sku == 'y_product')\r\n // dynamicOption.productId = '01t4x000008PckRAAS';\r\n // if (element.sku == 'z_product')\r\n // dynamicOption.productId = '01t4x000008PcknAAC';\r\n optionConfig['Dynamic Options'][index] = dynamicOption;\r\n\r\n if (!salesforceId) {\r\n this.dynamicOptionsToQueryStatic.push({ item: element, dynamicOption });\r\n }\r\n\r\n if (element.items.length) {\r\n let dynOptsBuild = this.buildOptions(payload, element, optionConfig['Dynamic Options'][index].optionConfigurations, true);\r\n optionConfig['Dynamic Options'][index].optionConfigurations = dynOptsBuild.load;\r\n //this.dynamicOptionsToQueryStatic.push(...dynOptsBuild.dynOptionsToQuery);\r\n }\r\n\r\n })\r\n } else {\r\n item.items.forEach((element, index) => {\r\n optionConfig['Other Options'][index] = {\r\n ProductCode: element.sku,\r\n ProductName: Object.keys({element})[0],\r\n optionId: element.externalId,\r\n selected: true,\r\n Quantity: element.qty ?? 1,\r\n configurationData: {},\r\n };\r\n this.addColumnsAndMetadataToConfigurationObject(payload, optionConfig['Other Options'][index].configurationData, element);\r\n if (element.items.length > 0) {\r\n optionConfig['Other Options'][index].optionConfigurations = this.buildOptions(payload, element, optionConfig['Other Options'][index].optionConfigurations).load;\r\n }\r\n });\r\n }\r\n \r\n \r\n return {load: optionConfig, dynOptionsToQuery: this.dynamicOptionsToQueryStatic};\r\n }\r\n protected clearNestedOptions(options: { [name: string]: ISfdcCpqPayloadOption[] }) {\r\n for (let option in options) {\r\n options[option].forEach(element => {\r\n element.selected = false;\r\n if (element.optionConfigurations) {\r\n element.optionConfigurations = this.clearNestedOptions(element.optionConfigurations);\r\n }\r\n });\r\n }\r\n return options;\r\n }\r\n\r\n public saveToSfdcCpq(payload: ISfdcCpqPayload, priceObject: IPriceObject) {\r\n let sr = this.$rootScope.context.sfdcCanvasRequest;\r\n let payloadOrig = payload;\r\n // clear out old options\r\n for (let feature in payload.data.product.optionConfigurations) {\r\n if (feature.isEqual(\"Dynamic Options\")) {\r\n payload.data.product.optionConfigurations[feature].forEach(option => {\r\n option.Quantity = 0;\r\n option.selected = false;\r\n }); // clear out dynamic options\r\n } else {\r\n payload.data.product.optionConfigurations[feature].forEach(option =>\r\n option.selected = false); // unselect all pre-defined product options\r\n // unselect all pre-defined product options\r\n payload.data.product.optionConfigurations[feature].forEach(option => {\r\n option.selected = false;\r\n //delete option['optionConfigurations'];\r\n //console.log(option.ProductCode, 'cleared');\r\n if (option.optionConfigurations) {\r\n option.optionConfigurations = this.clearNestedOptions(option.optionConfigurations);\r\n }\r\n //option.Quantity = 0;\r\n \r\n });\r\n }\r\n }\r\n\r\n let dynamicOptionsToQuery: { item: IPriceItem, dynamicOption: ISfdcCpqPayloadOption }[] = [];\r\n\r\n if (priceObject) {\r\n // first we process non-dynamic product options\r\n // we recurse through all the price items and try to find matching product \r\n // options that are not in the 'Dynamic Options' optionConfigurations object of the payload\r\n priceObject.items.forEach(item => {\r\n let foundInOptions = false;\r\n featureLoop:\r\n for (let feature in payload.data.product.optionConfigurations) {\r\n if (!feature.isEqual(\"Dynamic Options\")) {\r\n let options: ISfdcCpqPayloadOption[] = payload.data.product.optionConfigurations[feature];\r\n for (let option of options) {\r\n if (item.sku == option.ProductCode) {\r\n option.selected = true;\r\n option.Quantity = item.qty ?? 1;\r\n foundInOptions = true;\r\n\r\n if (item.items.length > 0) {\r\n option.optionConfigurations = this.buildOptions(payload, item, option.optionConfigurations).load;\r\n }\r\n // load configuration attributes also\r\n // we only add configuration attributes that are defined \r\n // in the configurationAttributes section of the json\r\n option.configurationData = option.configurationData || {};\r\n this.addColumnsAndMetadataToConfigurationObject(\r\n payload, option.configurationData, item);\r\n \r\n break featureLoop;\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (!foundInOptions) {\r\n // if it's not found in the options, then we try to add it as a dynamic product option: \r\n // tslint:disable-next-line:max-line-length\r\n // https://community.steelbrick.com/t5/Developer-Guidebook/Configurator-Integration-to-Third-Party-Web-Apps/ta-p/5575\r\n let dynamicFeature = payload.data.product.optionConfigurations[\"Dynamic Options\"];\r\n // salesforceId must be defined for dynamic product options to work\r\n let salesforceId = item.columns.salesforceId || item.metadata.salesforceId;\r\n if (dynamicFeature) {\r\n // first see if the dynamic product option is already there\r\n //let dynamicOption: ISfdcCpqPayloadOption =\r\n // dynamicFeature.find(dynOpt => dynOpt.ProductCode && dynOpt.ProductCode.isEqual(item.sku));\r\n //if (dynamicOption) {\r\n // dynamicOption.Quantity = item.qty;\r\n // dynamicOption.selected = true;\r\n //} else {\r\n let dynamicOption: ISfdcCpqPayloadOption = {\r\n productId: salesforceId,\r\n Quantity: item.qty,\r\n configurationData: {},\r\n selected: true,\r\n };\r\n \r\n\r\n if (item.items.length) {\r\n let dynOptsBuild = this.buildOptions(payload, item, dynamicOption.optionConfigurations, true);\r\n dynamicOption.optionConfigurations = dynOptsBuild.load;\r\n //dynamicOptionsToQuery.push(...dynOptsBuild.dynOptionsToQuery);\r\n }\r\n dynamicFeature.push(dynamicOption);\r\n\r\n // if the salesforceId wasn't provided directly,\r\n // then we make a call later to get the product id using the product code\r\n if (!salesforceId) {\r\n this.dynamicOptionsToQueryStatic.push({ item, dynamicOption });\r\n }\r\n this.addColumnsAndMetadataToConfigurationObject(\r\n payload,\r\n dynamicOption.configurationData,\r\n item\r\n );\r\n\r\n }\r\n }\r\n });\r\n\r\n // set the product level configuration attributes that correspond to price columns or price item metadata\r\n if (payload.data.product.configurationAttributes) {\r\n for (let prop in payload.data.product.configurationAttributes) {\r\n let attValue = this.getColumnOrMetaValue(prop, priceObject);\r\n if (attValue != null) {\r\n // priceObject corresponds to the top level product\r\n payload.data.product.configurationAttributes[prop] = attValue;\r\n }\r\n }\r\n }\r\n }\r\n\r\n let dynamicOptionsQueryPromise: ng.IPromise = new KPromise(null) as any;\r\n if (this.dynamicOptionsToQueryStatic.length) {\r\n dynamicOptionsQueryPromise = this.getProducts(this.dynamicOptionsToQueryStatic.map(o => o.item.sku)\r\n .removeNulls())\r\n .then(products => {\r\n this.dynamicOptionsToQueryStatic.forEach(dynOption => {\r\n let product2 = products.find(p => p.ProductCode.isEqual(dynOption.item.sku));\r\n if (!product2) {\r\n // tslint:disable-next-line:max-line-length\r\n let err = `Unable to add dynamic product option '${dynOption.item.sku}'. No matching product record was found.`;\r\n this.dialogService.alert({ msg: err, persist: true, type: eAlertType.error });\r\n throw err;\r\n } else {\r\n dynOption.dynamicOption.productId = product2.Id;\r\n }\r\n });\r\n });\r\n }\r\n\r\n // DEBUG\r\n // if (Environment.isDebug) {\r\n // payload.data.quote[\"KBMAXSB__Test__c\"] = \"blah blah\";\r\n // }\r\n // payload.data.product.optionConfigurations[\"DynamicFeature\"].push({\r\n // productId: \"01t41000003vzS3\",\r\n // Quantity: 2,\r\n // configurationData: {\r\n // KBMAXSB__Test__c: \"hey now\",\r\n // KBMAXSB__Number_Attribute__c: 444\r\n // }\r\n // });\r\n\r\n // payload.data.product.optionConfigurations[\"DynamicFeature\"].push({\r\n // productId: \"01t41000003vzS3\",\r\n // Quantity: 2,\r\n // configurationData: {\r\n // KBMAXSB__Test__c: \"hey now\",\r\n // KBMAXSB__Number_Attribute__c: 444\r\n // }\r\n // });\r\n\r\n dynamicOptionsQueryPromise.then(() => {\r\n Sfdc.canvas.client.publish(sr.client, {\r\n name: \"sfdccpq_save\",\r\n payload\r\n });\r\n });\r\n\r\n }\r\n}\r\n","import { NgService } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport {HubConnectionBuilder, JsonHubProtocol, HubConnection, LogLevel} from \"@microsoft/signalR\";\r\n//import {ConsoleLogger} from \"@aspnet/signalR\";\r\n//import {JsonHubProtocol} from \"@aspnet/signalR\";\r\n//import {LogLevel} from \"@aspnet/signalR\";\r\n\r\n// import * as signalR from \"@aspnet/signalr-client\";\r\n\r\n@NgService({\r\n token: Token.SignalRService,\r\n dependencies: [\r\n Token.$RootScope,\r\n Token.$Q,\r\n ]\r\n})\r\nexport class SignalrService {\r\n constructor(\r\n private $rootScope,\r\n private $q: ng.IQService\r\n ) {\r\n\r\n }\r\n \r\n private crudConnectionPromise: Promise;\r\n private notificationConnectionPromise: Promise;\r\n private crudConnection: HubConnection;\r\n private notificationConnection: signalR.HubConnection;\r\n // private crudHubProxy: signalR.HubProxy;\r\n // private notificationHubProxy: signalR.HubProxy;\r\n private stopping: boolean;\r\n\r\n private stop() {\r\n this.stopping = true;\r\n this.crudConnection.stop();\r\n this.notificationConnection.stop();\r\n }\r\n\r\n public start() {\r\n\r\n // adapted from https://docs.microsoft.com/en-us/aspnet/core/signalr/javascript-client?view=aspnetcore-2.1\r\n // Surprise, surprise, as of today (July, 2018) HubConnectionBuilder which the documentation references\r\n // isn't in the npm aspnet/signalr project.\r\n this.crudConnection = new (window).signalR.HubConnectionBuilder()\r\n .withUrl(\"/crudHub\", {\r\n serverTimeoutInMilliseconds: 100000000\r\n })\r\n .withHubProtocol(new JsonHubProtocol())\r\n .configureLogging((window).signalR.LogLevel.Information)\r\n .build(); \r\n\r\n this.notificationConnection = new (window).signalR.HubConnectionBuilder()\r\n .withUrl(\"/notificationHub\", {\r\n serverTimeoutInMilliseconds: 100000000\r\n })\r\n .withHubProtocol(new JsonHubProtocol())\r\n .configureLogging((window).signalR.LogLevel.Information)\r\n .build();\r\n\r\n var promises = [this.crudConnectionPromise = this.crudConnection.start(), this.notificationConnectionPromise = this.notificationConnection.start()];\r\n\r\n return this.$q.when(promises);\r\n }\r\n\r\n public notificationOn(eventName: string, callback?: (...result: any[]) => void) {\r\n if (this.notificationConnection) this.notificationConnection.on(eventName, callback);\r\n }\r\n\r\n public notificationOff(eventName: string, callback?: (...result: any[]) => void) {\r\n if (this.notificationConnection) this.notificationConnection.off(eventName, callback);\r\n }\r\n\r\n public notificationInvoke(methodName: string, ...data: any[]) {\r\n if (this.notificationConnectionPromise) {\r\n this.notificationConnectionPromise.then(() => {\r\n this.notificationConnection.invoke.apply(this.notificationConnection, [methodName].concat(data))\r\n .then((result) => {\r\n this.$rootScope.$apply(() => {\r\n });\r\n });\r\n });\r\n }\r\n }\r\n\r\n public on(eventName: string, callback?: (...result: any[]) => void) {\r\n if (this.crudConnection) this.crudConnection.on(eventName, callback);\r\n }\r\n\r\n public off(eventName: string, callback?: (...result: any[]) => void) {\r\n if (this.crudConnection) this.crudConnection.off(eventName, callback);\r\n }\r\n\r\n public invoke(methodName: string, ...data: any[]) {\r\n if (this.crudConnectionPromise) {\r\n this.crudConnectionPromise.then(() => {\r\n this.crudConnection.invoke.apply(this.crudConnection, [methodName].concat(data))\r\n .then((result) => {\r\n this.$rootScope.$apply(() => {\r\n });\r\n });\r\n });\r\n }\r\n }\r\n \r\n}\r\n","import { NgService } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { IRootScope } from \"@models\";\r\nimport { Utils } from \"@tools\";\r\n\r\n@NgService({\r\n token: Token.StorageService,\r\n dependencies: [\r\n Token.$RootScope\r\n ]\r\n})\r\nexport class StorageService {\r\n constructor(\r\n private $rootScope: IRootScope\r\n ) {\r\n\r\n }\r\n\r\n public getFallbackImage() {\r\n return `${this.$rootScope.context.publicStorageUrl}/assets/images/cube.png`;\r\n }\r\n\r\n public getAssetUrl(relativePath: string) {\r\n return `${this.$rootScope.context.publicStorageUrl}/assets/${relativePath}`;\r\n }\r\n\r\n public getMediaUrl(relativePath: string) {\r\n if (Utils.isAbsoluteUrl(relativePath)) {\r\n return relativePath;\r\n } else {\r\n return `${this.$rootScope.context.publicStorageUrl}/media/${relativePath}`;\r\n }\r\n }\r\n\r\n public getProfileImageUrl(relativePath: string) {\r\n if (Utils.isAbsoluteUrl(relativePath)) {\r\n return relativePath;\r\n } else {\r\n return `${this.$rootScope.context.publicStorageUrl}/profileimages/${relativePath}`;\r\n }\r\n }\r\n\r\n /**\r\n * Gets the absolute url of a generic public blob file. The relativePath given must include the container in this call (like media, mesh, etc)\r\n * @param relativePath \r\n */\r\n public getFileUrl(relativePath: string) {\r\n return `${this.$rootScope.context.publicStorageUrl}/${relativePath}`;\r\n }\r\n}\r\n","import { NgService } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { AuthService } from \"@app/services/auth.service\";\r\nimport { IRootScope } from \"@models\";\r\nimport { Transition, TransitionService } from \"@uirouter/angularjs\";\r\nimport { ILocationService } from \"angular\";\r\n\r\n\r\n@NgService({\r\n token: Token.TelemetryService,\r\n dependencies: [\r\n Token.$RootScope,\r\n Token.$Transitions,\r\n Token.$Location,\r\n Token.AuthService\r\n ]\r\n})\r\nexport class TelemetryService {\r\n constructor(\r\n private $rootScope: IRootScope,\r\n private $transitions: TransitionService,\r\n private $location: ILocationService,\r\n private authService: AuthService\r\n ) {\r\n authService.contextPromise.then(() => {\r\n if ($rootScope.context.appInsightsKey) {\r\n var snippet = {\r\n config: {\r\n instrumentationKey: $rootScope.context.appInsightsKey,\r\n disableAjaxTracking: true\r\n } as Microsoft.ApplicationInsights.IConfig\r\n } as Microsoft.ApplicationInsights.IConfig;\r\n var init = new Microsoft.ApplicationInsights[\"Initialization\"](snippet);\r\n this._appInsights = init.loadAppInsights() as Microsoft.ApplicationInsights.IAppInsights;\r\n\r\n $transitions.onSuccess({}, (transition: Transition) => {\r\n let state = transition.to();\r\n if (state && state.name && state.url && state.name != this.lastState && state.name != \"kb.admin\") {\r\n let name = this.lastState = state.name;\r\n if (name.startsWith(\"kb.\")) name = name.slice(3);\r\n name = name.replace(\".base.\", \".\");\r\n // name = name.replace(\".\", \"/\");\r\n // name = \"/\" + name;\r\n let url = [$location.protocol(), '://', $location.host(), $location.path()].join(''); //url with no query string\r\n this.trackPageView(name, url);\r\n }\r\n });\r\n }\r\n });\r\n }\r\n\r\n private lastState: string;\r\n private _appInsights: Microsoft.ApplicationInsights.IAppInsights;\r\n\r\n private setDefaultProperties(properties: any = null) {\r\n properties = properties || {};\r\n if (this.$rootScope.company && this.$rootScope.company.subdomain) {\r\n properties.Company = this.$rootScope.company.subdomain;\r\n }\r\n properties.App = \"Client\";\r\n return properties;\r\n }\r\n\r\n public trackPageView(name?: string, url?: string, properties?: any) {\r\n if (this._appInsights) {\r\n this._appInsights.trackPageView(name, url, this.setDefaultProperties(properties))\r\n }\r\n }\r\n\r\n public trackEvent(name?: string, properties?: any) {\r\n if (this._appInsights) {\r\n this._appInsights.trackEvent(name, this.setDefaultProperties(properties));\r\n }\r\n }\r\n\r\n public trackException(exception: Error) {\r\n if (this._appInsights) {\r\n this._appInsights.trackException(exception, null, this.setDefaultProperties());\r\n }\r\n }\r\n}\r\n","import { NgService } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { eClusterEnv, eSkin, IRootScope, ITheme } from \"@models\";\r\nimport { KPromise } from \"@rules\";\r\nimport { Color } from \"@tools\";\r\nimport { StateService, Transition, TransitionService } from \"@uirouter/angularjs\";\r\n\r\n@NgService({\r\n token: Token.ThemeService,\r\n dependencies: [\r\n Token.$RootScope,\r\n Token.$Http,\r\n Token.$Location,\r\n Token.$Transitions,\r\n Token.$State\r\n ]\r\n})\r\nexport class ThemeService {\r\n\r\n constructor(\r\n private $rootScope: IRootScope,\r\n private $http: ng.IHttpService,\r\n private $location: ng.ILocationService,\r\n private $transitions: TransitionService,\r\n private $state: StateService\r\n ) {\r\n this.defaultThemes = [\r\n {\r\n id: null,\r\n name: \"Default\",\r\n skin: eSkin.material,\r\n background: \"#f2f2f2\",\r\n input: \"#FFFFFF\",\r\n header: \"#025064\",\r\n primary: \"#025064\",\r\n accent: \"#ff8873\", //#FF9800\", //\"#ffd54f\", //\"#ff9800\", //\"#ef6c00\", //\"#ff8f00\", //\"#E3831C\",\r\n warn: \"#ff2102\",\r\n success: \"#049e8a\",\r\n border: \"#CCC\",\r\n dark: false,\r\n font: \"Roboto\",\r\n fontSize: 15,\r\n radius: 4\r\n },\r\n {\r\n id: -1,\r\n name: \"Night Launch\",\r\n skin: eSkin.material,\r\n background: \"#1a1a1a\",\r\n input: \"#242424\",\r\n header: \"#bfbfbf\",\r\n primary: \"#424242\",\r\n accent: \"#ffaf47\",\r\n warn: \"#e0583a\",\r\n success: \"#22a153\",\r\n border: \"#575757\",\r\n dark: true,\r\n font: \"Roboto\",\r\n fontSize: 15,\r\n radius: 2\r\n },\r\n {\r\n id: -2,\r\n name: \"Valyrian Steel\",\r\n skin: eSkin.material,\r\n background: \"#eeeeee\",\r\n input: \"#FFFFFF\",\r\n header: \"#535863\",\r\n primary: \"#535863\",\r\n accent: \"#ff5e00\",\r\n warn: \"#e33e1c\",\r\n success: \"#14a54a\",\r\n border: \"#b6c2e0\",\r\n dark: false,\r\n font: \"Roboto\",\r\n fontSize: 15,\r\n radius: 2\r\n },\r\n {\r\n id: -3,\r\n name: \"Midnight Bananas\",\r\n skin: eSkin.classic,\r\n background: \"#2b2b2b\",\r\n input: \"#2b2b2b\",\r\n header: \"#33702b\",\r\n primary: \"#33702b\",\r\n accent: \"#e7f043\",\r\n warn: \"#e33e1c\",\r\n success: \"#14a54a\",\r\n border: \"#a6ffad\",\r\n dark: true,\r\n font: \"Roboto\",\r\n fontSize: 15,\r\n radius: 2\r\n },\r\n {\r\n id: -4,\r\n name: \"Blood Money\",\r\n skin: eSkin.material,\r\n background: \"#eeeeee\",\r\n input: \"#ffffff\",\r\n header: \"#8c3333\",\r\n primary: \"#8c3333\",\r\n accent: \"#1F5454\",\r\n warn: \"#e33e1c\",\r\n success: \"#297029\",\r\n border: \"#b8d6d6\",\r\n dark: false,\r\n font: \"Roboto\",\r\n fontSize: 15,\r\n radius: 2\r\n },\r\n {\r\n id: -5,\r\n name: \"Apple II\",\r\n skin: eSkin.classic,\r\n background: \"#000000\",\r\n input: \"#000000\",\r\n header: \"#141414\",\r\n primary: \"#141414\",\r\n accent: \"#33fe33\",\r\n warn: \"#e33e1c\",\r\n success: \"#14a54a\",\r\n border: \"#33fe33\",\r\n dark: true,\r\n font: \"Roboto\",\r\n fontSize: 15,\r\n radius: 2\r\n },\r\n {\r\n id: -6,\r\n name: \"Salesforce Lightning\",\r\n skin: eSkin.material,\r\n background: \"#f7f7f7\",\r\n input: \"#ffffff\",\r\n header: \"#16325C\",\r\n primary: \"#16325C\",\r\n accent: \"#00A1E0\",\r\n warn: \"#e33e1c\",\r\n success: \"#14a54a\",\r\n border: \"#d8dde6\",\r\n dark: false,\r\n font: \"Roboto\",\r\n fontSize: 15,\r\n radius: 2\r\n },\r\n {\r\n id: -7,\r\n name: \"Classic\",\r\n skin: eSkin.material,\r\n background: \"#f2f2f2\",\r\n input: \"#FFFFFF\",\r\n header: \"#084860\",\r\n primary: \"#084860\", //#607D8B\", //\"#7986cb\", //\"#0097a7\", //\"#304ffe\", //\"#0d47a1\", //\"#084860\",\r\n accent: \"#E3831C\", //#FF9800\", //\"#ffd54f\", //\"#ff9800\", //\"#ef6c00\", //\"#ff8f00\", //\"#E3831C\",\r\n warn: \"#E33E1C\",\r\n success: \"#14A54A\",\r\n border: \"#CCC\",\r\n dark: false,\r\n font: \"Roboto\",\r\n fontSize: 15,\r\n radius: 4\r\n },\r\n ];\r\n\r\n let queryString = $location.search();\r\n\r\n this.loadTemplate().then(() => {\r\n this.parseAndLoad(this.getActiveTheme());\r\n });\r\n\r\n $transitions.onFinish({}, (transition: Transition) => {\r\n let from = transition.from().name;\r\n let to = transition.to().name;\r\n if ((to == \"sceneEdit\" && from != \"sceneEdit\") || from == \"sceneEdit\" && to != \"sceneEdit\") {\r\n this.parseAndLoad(this.getActiveTheme());\r\n }\r\n });\r\n }\r\n\r\n public defaultThemes: ITheme[];\r\n public themeCss: string;\r\n\r\n private loadTemplate(): Q.IPromise {\r\n // in debug, we get the css from the server so that it can be changed without stopping debugging\r\n if (this.$rootScope.clusterEnv == eClusterEnv.dev) {\r\n return this.$http.get(\"kbmax-theme.css\").then(r => {\r\n return this.themeCss = r.data;\r\n });\r\n } else {\r\n this.themeCss = this.$rootScope.context.themeCss;\r\n return new KPromise(this.themeCss) as Q.IPromise;\r\n }\r\n }\r\n\r\n public getDefaultTheme(id: number = null) {\r\n return this.defaultThemes.find(t => t.id == id);\r\n }\r\n\r\n public getActiveTheme(): ITheme {\r\n let queryString = this.$location.search();\r\n\r\n if (queryString[\"idtheme\"] && !this.$rootScope.context.sfdcCanvasRequest) {\r\n let idTheme = Number(queryString[\"idtheme\"]);\r\n if (idTheme > 0) {\r\n return this.$rootScope.context.theme;\r\n } else {\r\n return this.getDefaultTheme(idTheme);\r\n }\r\n }\r\n else if (this.$rootScope.context.sfdcCanvasRequest) {\r\n\r\n var sfTheme = this.getDefaultTheme(-6);\r\n //if they have a non-default theme setup, then we use the skin from that. This way they get the salesforce theme,\r\n //but with the skin they want (material or classic)\r\n if (this.$rootScope.companySettings.idTheme && this.$rootScope.companySettings.idTheme > 0) {\r\n sfTheme.skin = this.$rootScope.context.theme.skin;\r\n }\r\n //let overrideTheme = await this.$apiService.themes.getById(1);\r\n //sfTheme = overrideTheme;\r\n if (queryString['idtheme']) {\r\n return this.$rootScope.context.theme ?? sfTheme;\r\n }\r\n \r\n console.log(sfTheme);\r\n return sfTheme;\r\n }\r\n else if (\r\n (this.$state.current && this.$state.current.name == \"sceneEdit\" && !this.$state.transition)\r\n || (this.$state.transition && (this.$state.transition.to().name == \"sceneEdit\"))\r\n ) {\r\n return this.getDefaultTheme(-1);\r\n }\r\n else if (this.$rootScope.context.theme) {\r\n return this.$rootScope.context.theme;\r\n } else {\r\n return this.getDefaultTheme(this.$rootScope.companySettings.idTheme);\r\n }\r\n }\r\n\r\n public getRgbString(theme: ITheme, palette: string, shade: number, opacity: number, contrast: boolean, grayscale: boolean) {\r\n let c: Color = new Color(theme[palette]);\r\n\r\n let offset = shade - 50;\r\n if (theme.dark) offset = -offset;\r\n let percent = Math.abs(offset / 2);\r\n if (offset > 0) {\r\n c = Color.darken(c.getOriginalInput(), percent);\r\n } else if (offset < 0) {\r\n c = Color.lighten(c.getOriginalInput(), percent);\r\n }\r\n\r\n if (contrast) {\r\n if (c.isDark()) {\r\n c = new Color({ r: 250, g: 250, b: 250 });\r\n } else {\r\n c = new Color({ r: 17, g: 17, b: 17 });\r\n }\r\n }\r\n if (grayscale) {\r\n let hsv = c.toHsv();\r\n hsv.s = 0;\r\n c = new Color(hsv);\r\n }\r\n\r\n c.setAlpha(opacity);\r\n\r\n return c.toRgbString();\r\n }\r\n\r\n public parseTheme(theme?: ITheme): string {\r\n theme = theme || this.getDefaultTheme();\r\n let hueRegex = new RegExp(\r\n // tslint:disable-next-line:max-line-length\r\n '(\\'|\")?{{\\\\s*(background|input|primary|accent|warn|success|border|header)_(color|contrast|grayscale)_?(\\\\d\\\\.?\\\\d*)?_?(\\\\d\\\\.?\\\\d*)?\\\\s*}}(\\\"|\\')?', \"g\"\r\n );\r\n let css = this.themeCss.replace(\r\n hueRegex,\r\n (match: string, quotes: string, palette: string, cType: string, shade: string, opacity: string) => {\r\n let shadeNum: number = shade ? Number(shade) : 50;\r\n let opacityNum: number = opacity == null ? 1 : Number(opacity) / 100;\r\n return this.getRgbString(theme, palette, shadeNum, opacityNum, (cType == \"contrast\"), (cType == \"grayscale\"));\r\n });\r\n\r\n // border-radius\r\n css = css.replaceAll(\"'{{radius}}'\", theme.radius + \"px\");\r\n css = css.replaceAll(\"'{{fontSize}}'\", theme.fontSize + \"px\");\r\n \r\n // font\r\n if (theme.font) {\r\n css = css.replaceAll(\"{{font}}\", theme.font);\r\n }\r\n\r\n if (theme.customFontUrl) {\r\n css = `@import url('${theme.customFontUrl}');\\n` + css;\r\n }\r\n\r\n return css;\r\n }\r\n\r\n public setThemeToHead(themeCss: string) {\r\n let style = document.getElementById(\"kbmax-theme\") as HTMLStyleElement;\r\n if (!style) {\r\n style = document.createElement(\"style\");\r\n style.id = \"kbmax-theme\";\r\n }\r\n style.type = \"text/css\";\r\n style.innerHTML = themeCss;\r\n if (!style.parentElement) {\r\n document.head.appendChild(style);\r\n }\r\n }\r\n\r\n public refreshActiveTheme() {\r\n this.parseAndLoad(this.getActiveTheme());\r\n }\r\n\r\n public parseAndLoad(theme?: ITheme) {\r\n let css = this.parseTheme(theme);\r\n this.setThemeToHead(css);\r\n this.$rootScope.currentTheme = theme;\r\n }\r\n}\r\n","import { NgService } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { IFieldUploadOptions, IRootScope } from \"@models\";\r\nimport * as angular from \"angular\";\r\n\r\n@NgService({\r\n token: Token.UploadService,\r\n dependencies: [\r\n Token.$Q,\r\n Token.$Http,\r\n Token.$RootScope,\r\n ]\r\n})\r\nexport class UploadService {\r\n\r\n constructor(\r\n private $q: ng.IQService,\r\n private $http: ng.IHttpService,\r\n private $rootScope: IRootScope\r\n ) {\r\n this.uploadInputHelper = angular.element('');\r\n\r\n }\r\n\r\n public promptUserToChooseFile(accept?: string): ng.IPromise {\r\n let deferred = this.$q.defer();\r\n this.uploadInputHelper = angular.element('');\r\n if (this.currentCallback) this.uploadInputHelper.unbind(\"change\", this.currentCallback);\r\n this.uploadInputHelper.val(null); //clear the value otherwise the change event won't fire if another file is picked\r\n if (accept) {\r\n this.uploadInputHelper.attr(\"accept\", accept);\r\n } else {\r\n this.uploadInputHelper.removeAttr(\"accept\");\r\n }\r\n this.currentCallback = e => {\r\n let element: any = e.target;\r\n this.uploadInputHelper[0].removeEventListener(\"change\", this.currentCallback);\r\n this.currentCallback = null;\r\n if (!element || element.files.length == 0) {\r\n deferred.reject();\r\n return;\r\n }\r\n let file = element.files[0];\r\n file.fullPath = this.uploadInputHelper.val();\r\n deferred.resolve(file);\r\n };\r\n this.uploadInputHelper[0].addEventListener(\"change\", this.currentCallback);\r\n this.uploadInputHelper[0].click();\r\n return deferred.promise;\r\n }\r\n\r\n public promptUserToChooseFiles(): ng.IPromise {\r\n let deferred = this.$q.defer();\r\n this.uploadInputHelper = angular.element('');\r\n this.uploadInputHelper.attr(\"multiple\", \"multiple\");\r\n if (this.currentCallback) this.uploadInputHelper.unbind(\"change\", this.currentCallback);\r\n this.uploadInputHelper.val(null); //clear the value otherwise the change event won't fire if another file is picked\r\n\r\n this.currentCallback = e => {\r\n this.uploadInputHelper.removeAttr(\"multiple\");\r\n let element: any = e.target;\r\n this.uploadInputHelper.unbind(\"change\", this.currentCallback);\r\n this.currentCallback = null;\r\n if (!element || element.files.length == 0) {\r\n deferred.reject();\r\n return;\r\n }\r\n let val = this.uploadInputHelper.val();\r\n let files = [];\r\n for (let f of element.files) {\r\n f.fullPath = val;\r\n files.push(f);\r\n } \r\n deferred.resolve(files);\r\n };\r\n this.uploadInputHelper.bind(\"change\", this.currentCallback);\r\n this.uploadInputHelper.click();\r\n return deferred.promise;\r\n\r\n }\r\n\r\n public uploadAttachment(file: File, entity, url): ng.IPromise {\r\n let postConfig: ng.IRequestShortcutConfig = {\r\n // add this to not serialize form data\r\n transformRequest: angular.identity,\r\n // set header to undefined so the browser sets the multipart content type\r\n headers: { \"Content-Type\": undefined }\r\n };\r\n let deferred = this.$q.defer();\r\n let formData = new FormData();\r\n formData.append(\"file\", file);\r\n formData.append(\"json\", JSON.stringify(entity));\r\n this.$http.post(url, formData, postConfig).then(response => {\r\n // returns the filename of the new node in the upload scene\r\n let uploadResult = response.data as any;\r\n deferred.resolve(uploadResult);\r\n }, reason => {\r\n deferred.reject(reason);\r\n });\r\n return deferred.promise;\r\n }\r\n\r\n public uploadFileToMedia(file: File, dir: string, apiPath: string = \"api/media\"): ng.IPromise {\r\n let d = this.$q.defer();\r\n let xhr = new XMLHttpRequest();\r\n let formData = new FormData();\r\n formData.append(\"file\", file);\r\n formData.append(\"dir\", dir);\r\n xhr.onreadystatechange = (e => {\r\n if (xhr.readyState == 4) {\r\n if (xhr.status == 200) {\r\n d.resolve();\r\n } else {\r\n d.reject();\r\n }\r\n }\r\n });\r\n // xhr.upload.onload = d.resolve;\r\n xhr.upload.onprogress = d.notify;\r\n // xhr.addEventListener(\"error\", d.reject);\r\n xhr.addEventListener(\"abort\", d.reject, false);\r\n xhr.open(\"POST\", apiPath + \"/upload\", true);\r\n // xhr.setRequestHeader(\"Content-Type\", \"multipart/form-data\");\r\n // xhr.setRequestHeader(\"x-ms-version\", \"2014-02-14\");\r\n // xhr.setRequestHeader(\"x-ms-date\",(new Date()).toISOString());\r\n // TODO: kbmax3dev is hardcoded. Need a way to determine the correct account to use (maybe Web.config?)\r\n // xhr.setRequestHeader(\"Authentication\", \"SharedKey kbmax3dev:\" + signature);\r\n // xhr.setRequestHeader(\"x-ms-blob-type\", \"BlockBlob\");\r\n xhr.send(formData);\r\n return d.promise;\r\n }\r\n\r\n public uploadProfileImage(file: File, userId: number): ng.IPromise {\r\n let url = \"/api/users/profileimage\";\r\n let postConfig: ng.IRequestShortcutConfig = {\r\n // add this to not serialize form data\r\n transformRequest: angular.identity,\r\n // set header to undefined so the browser sets the multipart content type\r\n headers: { \"Content-Type\": undefined }\r\n };\r\n let formData = new FormData();\r\n formData.append(\"userId\", userId.toString());\r\n formData.append(\"file\", file, file.name);\r\n\r\n let deferred = this.$q.defer();\r\n // post the file\r\n this.$http.put(url, formData, postConfig).then(response => {\r\n // returns the filename of the new node in the upload scene\r\n let uploadResult = response.data as any;\r\n deferred.resolve(uploadResult.filename);\r\n }, reason => {\r\n deferred.reject(reason);\r\n });\r\n\r\n return deferred.promise;\r\n }\r\n\r\n public importConfigurator(file: File): ng.IPromise {\r\n var formData = new FormData();\r\n formData.append(\"file\", file);\r\n return this.uploadFile(formData, \"api/admin/products/import\");\r\n }\r\n\r\n public uploadConfiguredProductFile(file: File, options: IFieldUploadOptions = {convertPdfToImage: false}): ng.IPromise {\r\n var formData = new FormData();\r\n formData.append(\"file\", file);\r\n formData.append(\"convertPdfToImage\", options.convertPdfToImage.toString());\r\n return this.uploadFile(formData, \"api/quotes/filefromconfiguratorfield\"); \r\n }\r\n\r\n public uploadQuoteFile(file: File, options: IFieldUploadOptions = {convertPdfToImage: false}): ng.IPromise {\r\n var formData = new FormData();\r\n formData.append(\"file\", file);\r\n formData.append(\"convertPdfToImage\", options.convertPdfToImage.toString());\r\n return this.uploadFile(formData, \"api/quotes/filefromquoteheaderfield\");\r\n }\r\n\r\n public uploadFile(formData: FormData, url: string): ng.IPromise {\r\n let postConfig: ng.IRequestShortcutConfig = {\r\n // add this to not serialize form data\r\n transformRequest: angular.identity,\r\n // set header to undefined so the browser sets the multipart content type\r\n headers: { \"Content-Type\": undefined },\r\n tracker: this.$rootScope.contentTracker\r\n };\r\n let deferred = this.$q.defer();\r\n let xhr = new XMLHttpRequest();\r\n this.$http.post(url, formData, postConfig).then(response => {\r\n // returns the filename of the new node in the upload scene\r\n let uploadResult = response.data as any;\r\n deferred.resolve(uploadResult);\r\n }, reason => {\r\n deferred.reject(reason);\r\n });\r\n return deferred.promise;\r\n }\r\n\r\n private currentCallback: (e) => void;\r\n private uploadInputHelper: JQuery;\r\n\r\n}\r\n","import { AuthService } from \"@app/services/auth.service\";\r\n\r\nexport interface IBaseScope extends ng.IScope {\r\n\r\n}\r\n\r\nexport class BaseController {\r\n /**\r\n * a callback used by ui-router to notify us when query string parameters have been changed.\r\n * @param changedParams\r\n * @param $transition$\r\n */\r\n public uiOnParamsChanged(changedParams, $transition$) {\r\n // do something with the changed params\r\n // you can inspect $transition$ to see the what triggered the dynamic params change.\r\n }\r\n}\r\n","import { NgView } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { ApiService, CrudClient } from \"@app/services/api.service\";\r\nimport { AuthService } from \"@app/services/auth.service\";\r\nimport { CrudService } from \"@app/services/crud.service\";\r\nimport { DialogService } from \"@app/services/dialog.service\";\r\nimport { DrawerService } from \"@app/services/drawer.service\";\r\nimport { SignalrService } from \"@app/services/signalr.service\";\r\nimport { BaseController, IBaseScope } from \"@app/views/base.view\";\r\nimport { DialogButton, eAlertType, eViewType, IRootScope } from \"@models\";\r\nimport { Constructor, events, icons } from \"@tools\";\r\nimport { StateParams, StateService, Transition, TransitionService } from \"@uirouter/angularjs\";\r\nimport * as angular from \"angular\";\r\n\r\nexport interface ICrudScope extends IBaseScope {\r\n model: T;\r\n save: () => ng.IPromise;\r\n cancel: () => void;\r\n delete: () => ng.IPromise;\r\n isEdit: boolean;\r\n isNew: boolean;\r\n isView: boolean;\r\n form: ng.IFormController;\r\n validation: any;\r\n}\r\n\r\n@NgView({\r\n token: Token.CrudView,\r\n dependencies: [\r\n Token.$Scope,\r\n Token.CrudService,\r\n Token.Model\r\n ],\r\n resolves: [\r\n {\r\n name: \"model\",\r\n dependencies: [\r\n Token.$StateParams,\r\n Token.AuthService,\r\n Token.$RootScope,\r\n Token.ApiService\r\n ],\r\n // tslint:disable-next-line:object-literal-shorthand\r\n fn: function( // need to use \"function\" instead of arrow here because we use \"this\" to get the api client\r\n $stateParams: StateParams,\r\n authService: AuthService,\r\n $rootScope: IRootScope,\r\n api: ApiService\r\n ) {\r\n let constructor = this as Constructor;\r\n // would like to check the state here to get the view type, \r\n // but there is a bug that is sending the old state: \r\n // https://github.com/angular-ui/ui-router/issues/238\r\n // instead we'll look for the id state parameter, which shouldn't be there for the new screens\r\n if ($stateParams.id) {\r\n return authService.authPromise.then(() => {\r\n return constructor.prototype.client(api).getById($stateParams.id, $rootScope.contentTracker);\r\n });\r\n } else {\r\n return authService.authPromise;\r\n }\r\n }\r\n }\r\n ]\r\n})\r\nexport class CrudController extends BaseController {\r\n\r\n constructor(\r\n public $scope: ICrudScope,\r\n public agg: CrudService,\r\n model: T\r\n ) {\r\n\r\n super();\r\n\r\n this.$http = agg.$http;\r\n this.$stateParams = Object.assign({}, agg.$stateParams);//$stateParams is actually a global object that is changed before $destroy is called, so we create a clone of it so that it's static for the life of this view\r\n this.$rootScope = agg.$rootScope;\r\n this.$state = agg.$state;\r\n this.$window = agg.$window;\r\n this.dialogService = agg.dialogService;\r\n this.drawerService = agg.drawerService;\r\n this.$q = agg.$q;\r\n this.signalrService = agg.signalrService;\r\n this.api = agg.api;\r\n this.$transitions = agg.$transitions;\r\n\r\n setTimeout(() => {\r\n this.$q.all(this.loadPromises).finally(() => {\r\n this.markChangesClean();\r\n });\r\n });\r\n\r\n let offTransition = this.$transitions.onStart({}, (transition: Transition) => {\r\n if (this.bypassUnsavedConfirmation) return;\r\n // When selecting items in the adminBaseController tree, for instance, this call\r\n // is sometimes made, so we'll check to ensure we're actually navigating out of\r\n // the page.\r\n if (transition.from().name == transition.to().name) return;\r\n if (!this.modelIsClean()) {\r\n let d = this.$q.defer();\r\n this.dialogService.confirm(loc.msg_confirmunsavedchanges, () => {\r\n d.resolve(true);\r\n }, () => {\r\n d.resolve(false);\r\n });\r\n return d.promise as Promise;\r\n }\r\n return true;\r\n });\r\n\r\n let onNavigateAway = e => {\r\n if (this.bypassUnsavedConfirmation) return;\r\n if (!this.modelIsClean()) {\r\n // If we haven't been passed the event get the window.event\r\n e = e || window.event;\r\n\r\n let message = loc.msg_confirmunsavedchanges;\r\n\r\n // For IE6-8 and Firefox prior to version 4\r\n if (e) {\r\n e.returnValue = message;\r\n }\r\n\r\n // For Chrome, Safari, IE8+ and Opera 12+\r\n return message;\r\n }\r\n return null;\r\n };\r\n\r\n window.onbeforeunload = onNavigateAway;\r\n\r\n let offOnLogin = this.$rootScope.$on(events.loginSuccessful, () => {\r\n this.subscribe();\r\n });\r\n\r\n $scope.$on(\"$destroy\", () => {\r\n window.onbeforeunload = null;\r\n offTransition();\r\n offOnLogin();\r\n this.unsubscribe();\r\n });\r\n\r\n $scope.model = model;\r\n $scope.validation = {};\r\n\r\n // set view variables to make it easy for views to bind to\r\n if (this.$state.current.data) {\r\n $scope.isEdit = (this.$state.current.data.viewType == eViewType.edit);\r\n $scope.isNew = (this.$state.current.data.viewType == eViewType.new);\r\n $scope.isView = (this.$state.current.data.viewType == eViewType.view);\r\n }\r\n\r\n $scope.cancel = () => {\r\n this.onCancel();\r\n this.bypassUnsavedConfirmation = true;\r\n this.$window.history.back();\r\n this.unsubscribe();\r\n };\r\n\r\n $scope.delete = () => {\r\n return this.delete();\r\n };\r\n\r\n $scope.save = () => {\r\n return this.save().then(() => {\r\n this.markChangesClean();\r\n });\r\n };\r\n\r\n this.handleResponse = (responseData, responseStatus) => {\r\n $scope.validation = this.getValidationObject(responseData, responseStatus);\r\n\r\n if ($scope.validation) {\r\n let alertMsg = $scope.validation.form || loc.msg_formerror;\r\n this.dialogService.alert({ type: eAlertType.error, msg: alertMsg });\r\n } else if (responseStatus == 500) {\r\n this.dialogService.alert({ type: eAlertType.error, msg: loc.msg_500error });\r\n }\r\n };\r\n\r\n this.subscribe();\r\n\r\n }\r\n\r\n public $http: ng.IHttpService;\r\n public $stateParams: any;\r\n public $rootScope: IRootScope;\r\n public $state: StateService;\r\n public $window: ng.IWindowService;\r\n public dialogService: DialogService;\r\n public drawerService: DrawerService;\r\n public $q: ng.IQService;\r\n public signalrService: SignalrService;\r\n public api: ApiService;\r\n public $transitions: TransitionService;\r\n\r\n public isSaving: boolean;\r\n protected cleanModel: T;\r\n protected bypassUnsavedConfirmation: boolean;\r\n protected loadPromises: Q.IPromise[] = [];\r\n public deleteMsg: string = loc.msg_confirmdelete;\r\n public handleResponse: (responseData: any, responseStatus: any) => any;\r\n \r\n public client(api: ApiService): CrudClient { throw new Error(\"This method is abstract\"); }\r\n public onSuccess(): void { throw new Error(\"This method is abstract\"); }\r\n public onCancel(): void { }\r\n public onDelete(): void { throw new Error(\"crudController.onDelete is abstract\"); }\r\n public webSocketEntityType(): string { return null; }\r\n public waitForRefresh(): boolean { return false; }\r\n\r\n protected save(): ng.IHttpPromise {\r\n if (this.$scope.isEdit) {\r\n return this.savePut();\r\n } else if (this.$scope.isNew) {\r\n return this.savePost();\r\n }\r\n }\r\n\r\n protected savePut(): ng.IPromise {\r\n if (!this.isSaving) {\r\n this.isSaving = true;\r\n return this.$http.put(\r\n `${this.client(this.api).baseUrl}/${this.$stateParams.id}?waitForRefresh=${this.waitForRefresh()}`,\r\n this.getModelForSave(),\r\n { tracker: this.$rootScope.contentTracker }\r\n ).then(r => {\r\n this.setUpdatedModel(r.data);\r\n this.onSuccess();\r\n this.$scope.$broadcast(\"saveSuccess\", r.data);\r\n },\r\n (r: ng.IHttpResponse) => {\r\n this.handleResponse(r.data, r.status);\r\n })\r\n .finally(() => {\r\n this.isSaving = false;\r\n });\r\n }\r\n }\r\n\r\n protected savePost(): ng.IPromise {\r\n if (!this.isSaving) {\r\n this.isSaving = true;\r\n return this.$http.post(\r\n `${this.client(this.api).baseUrl}?waitForRefresh=${this.waitForRefresh()}`,\r\n this.getModelForSave(),\r\n { tracker: this.$rootScope.contentTracker }\r\n ).then(r => {\r\n this.setUpdatedModel(r.data);\r\n this.onSuccess();\r\n this.$scope.$broadcast(\"saveSuccess\", r.data);\r\n this.subscribe();\r\n },\r\n (r: ng.IHttpResponse) => {\r\n this.handleResponse(r.data, r.status);\r\n })\r\n .finally(() => {\r\n this.isSaving = false;\r\n });\r\n }\r\n }\r\n\r\n public delete() {\r\n let deferred = this.$q.defer();\r\n\r\n this.dialogService.dialog({\r\n content: this.deleteMsg,\r\n buttons: [\r\n new DialogButton(loc.ok, icons.success, args => {\r\n this.unsubscribe(); //unsubscribe before we delete, otherwise we get the notification about the deletion before we've left the state\r\n this.client(this.api).delete(this.$stateParams.id).then(() => {\r\n this.bypassUnsavedConfirmation = true;\r\n deferred.resolve();\r\n this.onDelete();\r\n });\r\n }),\r\n new DialogButton(loc.cancel, icons.cancel, args => {\r\n deferred.reject();\r\n })\r\n ]\r\n });\r\n\r\n return deferred.promise;\r\n }\r\n\r\n protected modelIsClean() {\r\n return angular.equals(this.cleanModel, angular.copy(this.getModelForSave()));\r\n }\r\n\r\n protected getModelForSave() {\r\n return this.$scope.model;\r\n }\r\n\r\n protected setUpdatedModel(model: T) {\r\n this.$scope.model = model;\r\n }\r\n\r\n protected markChangesClean() {\r\n this.cleanModel = angular.copy(this.getModelForSave());\r\n }\r\n\r\n public getValidationObject(responseData, responseStatus) {\r\n let o;\r\n if (responseStatus == 400) {\r\n o = {};\r\n for (let prop in responseData) {\r\n // ignore the json type property\r\n if (prop !== \"$type\") {\r\n let newProp = prop === \"\" ? \"form\" : prop;\r\n let sections = newProp.split(\".\");\r\n sections.forEach((section, key) => {\r\n sections[key] = section.toCamelCase();\r\n });\r\n newProp = sections.join(\".\");\r\n o[newProp] = responseData[prop].join(\"\\n\");\r\n }\r\n }\r\n }\r\n\r\n return o;\r\n }\r\n\r\n private onSocketRelationshipEdited = (editedId: number, relationshipName: string) => {\r\n let callback = this.relationshipEditedCallbacks[relationshipName];\r\n if (callback && editedId == this.$stateParams.id) {\r\n this.client(this.api).getById(editedId).then(r => callback(r));\r\n }\r\n }\r\n\r\n /**\r\n * called when the entity has been deleted. Can be overriden for custom behavior\r\n * @param editedId\r\n */\r\n protected onSocketDeleted() {\r\n this.dialogService.alert({\r\n type: eAlertType.error,\r\n msg: \"Sorry. This entity has just been deleted by another user.\"\r\n });\r\n setTimeout(() => { this.onDelete(); }, 1000);\r\n }\r\n private onSocketDeletedDelegate = (editedId: number) => {\r\n if (editedId == this.$stateParams.id) {\r\n this.onSocketDeleted();\r\n }\r\n }\r\n\r\n /**\r\n * called when the entity has been edited by another consumer. Can be overriden for custom behavior.\r\n * @param editedId\r\n */\r\n protected onSocketEdited() {\r\n this.client(this.api).getById(this.$stateParams.id).then(r => {\r\n this.setUpdatedModel(r);\r\n });\r\n }\r\n private onSocketEditedDelegate = (editedId: number) => {\r\n if (editedId == this.$stateParams.id) {\r\n this.onSocketEdited();\r\n }\r\n }\r\n\r\n public subscribe() {\r\n this.unsubscribe();\r\n let entityType = this.webSocketEntityType();\r\n if (!entityType || !this.$stateParams.id) return;\r\n\r\n this.signalrService.invoke(\"subscribe\", this.$rootScope.company.uniqueName, entityType, this.$stateParams.id);\r\n this.signalrService.on(\"edited\", this.onSocketEditedDelegate);\r\n this.signalrService.on(\"deleted\", this.onSocketDeletedDelegate);\r\n this.signalrService.on(\"relationshipEdited\", this.onSocketRelationshipEdited);\r\n }\r\n\r\n public unsubscribe() {\r\n // console.log(\"Unsubscribing...\");\r\n let entityType = this.webSocketEntityType();\r\n if (!entityType || !this.$stateParams.id) return;\r\n this.signalrService.invoke(\"unsubscribe\", this.$rootScope.company.uniqueName, entityType, this.$stateParams.id);\r\n this.signalrService.off(\"edited\", this.onSocketEditedDelegate);\r\n this.signalrService.off(\"deleted\", this.onSocketDeletedDelegate);\r\n this.signalrService.off(\"relationshipEdited\", this.onSocketRelationshipEdited);\r\n }\r\n\r\n private relationshipEditedCallbacks: any = {};\r\n public onRelationshipEdited(property: string, callback: (entity: any) => void) {\r\n this.relationshipEditedCallbacks[property] = callback;\r\n }\r\n}\r\n","import { NgView } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { ApiService } from \"@app/services/api.service\";\r\nimport { CrudService } from \"@app/services/crud.service\";\r\nimport { CrudController, ICrudScope } from \"@app/views/crud.view\";\r\nimport { eViewType, IContact, ICustomer } from \"@models\";\r\nimport { icons } from \"@tools\";\r\n\r\nexport interface IContactScope extends ICrudScope {\r\n customers: ICustomer[];\r\n}\r\n\r\n@NgView({\r\n token: Token.ContactView,\r\n inherit: [Token.CrudView]\r\n})\r\nexport class ContactController extends CrudController {\r\n\r\n constructor(\r\n public $scope: IContactScope,\r\n crudService: CrudService,\r\n model: IContact\r\n ) {\r\n\r\n super(\r\n $scope,\r\n crudService,\r\n model\r\n );\r\n this.drawerService.setHelpUrl(\"Contacts\");\r\n\r\n let viewType = this.$state.current.data.viewType;\r\n\r\n if ($scope.model) {\r\n this.deleteMsg = loc.msg_deleterecord.format(\r\n loc.contact_title,\r\n $scope.model.firstName + \" \" + $scope.model.lastName\r\n );\r\n }\r\n\r\n if (viewType == eViewType.new) {\r\n\r\n $scope.model = {\r\n idCompany: this.$rootScope.company.id,\r\n shipToBillingAddress: true\r\n } as any;\r\n }\r\n\r\n // customers\r\n this.$http.get(\"/api/customers/selections\").then(response => $scope.customers = response.data);\r\n\r\n // add drawers\r\n if ($scope.isEdit || $scope.isNew) {\r\n let drDelete = this.drawerService.addDrawer(icons.deleter, loc.deleter, $scope.delete, $scope.isEdit);\r\n let drSave = this.drawerService.addDrawer(icons.save, loc.save, $scope.save);\r\n let drCancel = this.drawerService.addDrawer(icons.cancel, loc.cancel, $scope.cancel);\r\n } else {\r\n let drEdit = this.drawerService.addDrawer(icons.edit, loc.edit, () => {\r\n this.$state.go(\"kb.admin.contactEdit\", { id: $scope.model.id });\r\n }, this.$rootScope.user.canModifyCustomers);\r\n let drDelete = this.drawerService.addDrawer(\r\n icons.deleter,\r\n loc.deleter,\r\n $scope.delete,\r\n this.$rootScope.user.canModifyCustomers\r\n );\r\n }\r\n\r\n }\r\n\r\n public client(api: ApiService) {\r\n return api.contacts;\r\n }\r\n\r\n public waitForRefresh() {\r\n return true;\r\n }\r\n\r\n public onSuccess() {\r\n this.$state.go(\"kb.contacts\");\r\n }\r\n public onDelete() {\r\n this.$state.go(\"kb.contacts\");\r\n }\r\n}\r\n","import { IColumnScope } from \"@app/components/kb-column/kb-column.component\";\r\nimport { NgView } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { IEnumFilter } from \"@app/filters/enum.filter\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { ApiService, CrudClient, ProductClient } from \"@app/services/api.service\";\r\nimport { DrawerService } from \"@app/services/drawer.service\";\r\nimport { SearchService } from \"@app/services/search.service\";\r\nimport { BaseController, IBaseScope } from \"@app/views/base.view\";\r\nimport { DialogButton, eAttributeType, eFilterControl, eFilterSource, eFilterType, eProductSortBy, IFilter, IKbRole, IMetaProperty, ISavedSearch, ISearchArgs, meta } from \"@models\";\r\nimport { icons } from \"@tools\";\r\nimport { TransitionOptions } from \"@uirouter/angularjs\";\r\nimport { IPromiseTracker } from \"angular\";\r\nimport { IProductsScope } from \"./products/products.view\";\r\n\r\nexport interface ISearchBinding{\r\n selected?: ISavedSearch;\r\n search?: ISavedSearch;\r\n}\r\n\r\nexport interface ISearchScope extends IBaseScope {\r\n allowSearch: boolean;\r\n availableFilters: IFilter[];\r\n results: T[];\r\n query: (append?: boolean) => ng.IPromise;\r\n suggest: (q: string) => ng.IPromise;\r\n suggestValueField: string;\r\n columns: IColumnScope[]; // gets filled by the view... useful for picking the fields we want returned in the query\r\n filterSource: {};\r\n addFilter: (f: IFilter) => void;\r\n removeFilter: (f: IFilter) => void;\r\n infiniteScroll: () => void;\r\n reload: (force?: boolean) => void;\r\n sort: (col: IColumnScope) => void;\r\n toggleFilters: () => void;\r\n modelTypes: { label: string; state: string; type: string }[];\r\n modelTypeChange: (modelType: { label: string; state: string; type: string }) => void;\r\n savedSearches: ISavedSearch[];\r\n editSearch: (search?: ISavedSearch) => void;\r\n deleteSearch: (s: ISavedSearch) => ng.IPromise;\r\n canDeleteSearch: (s: ISavedSearch) => boolean;\r\n binding: ISearchBinding;\r\n drawerService: DrawerService;\r\n savedSearchEnabled: boolean;\r\n /** if you don't want a grid for the results, then set this to true and use the slot kb-search-grid-custom-results instead of kb-search-grid-results */\r\n customResults: boolean; \r\n}\r\n\r\nexport interface ISaveSearchDialogScope extends ng.IScope {\r\n roles?: IKbRole[];\r\n validation?: {\r\n name?: string;\r\n };\r\n model?: {\r\n name?: string;\r\n roles?: IKbRole[];\r\n };\r\n}\r\n\r\n/**\r\n * base class for handling search pages. \r\n */\r\n@NgView({\r\n token: Token.SearchView,\r\n dependencies: [\r\n Token.$Scope,\r\n Token.SearchService\r\n ]\r\n})\r\nexport class SearchController extends BaseController {\r\n constructor(\r\n protected $scope: ISearchScope,\r\n public agg: SearchService,\r\n public bypassInit: boolean = false //for derived classes (like products view) that need to explicitly call init to have a chance to fill in other scope items first\r\n ) {\r\n\r\n super();\r\n \r\n $scope.drawerService = agg.drawerService;\r\n $scope.binding = { selected: null, search: null };\r\n $scope.results = [];\r\n $scope.savedSearchEnabled = false; //disabled by default. Derived controllers can override\r\n $scope.allowSearch = true;\r\n\r\n $scope.query = (append: boolean = false) => {\r\n let filters: IFilter[] = []\r\n .concat($scope.binding.search.enabled ? $scope.binding.search.filters : [])\r\n .concat(this.getExtraFilters());\r\n if(append && this.epoch){\r\n //if we are appending to the infinite scroll, use the epoch as a filter so that we don't get duplicates\r\n filters.push(\r\n {\r\n property: \"createdDate\",\r\n control: eFilterControl.dateRange,\r\n type: eFilterType.property,\r\n max: this.epoch\r\n } as IFilter\r\n );\r\n } \r\n if(!this.epoch){\r\n this.epoch = new Date();\r\n }\r\n this.postProcessFilters(filters);\r\n let sortInfo = this.getSortInfo();\r\n\r\n let args: ISearchArgs = {\r\n skip: append ? $scope.results.length : 0,\r\n take: this.pageSize,\r\n fields: this.fields(),\r\n query: $scope.binding.search.query,\r\n sortField: sortInfo.sortField,\r\n descending: sortInfo.descending,\r\n filters,\r\n nestedPath: this.getNestedPath(),\r\n nestedFields: this.nestedFields()\r\n };\r\n let tracker = append ? agg.$rootScope.infiniteScrollTracker : agg.$rootScope.contentTracker;\r\n\r\n return this.searchCall(args, tracker).then(r => {\r\n this.massageResults(r);\r\n append ? $scope.results.pushArray(r) : $scope.results = r;\r\n return r;\r\n });\r\n };\r\n\r\n $scope.suggestValueField = \"name\";\r\n $scope.suggest = query => {\r\n if (query) {\r\n return this.client(agg.api).suggest({query, fields: [$scope.suggestValueField]});\r\n }\r\n };\r\n \r\n $scope.addFilter = f => {\r\n let newFilter = JSON.parse(JSON.stringify(f));\r\n $scope.binding.search.filters.push(newFilter);\r\n this.fillFilters();\r\n };\r\n $scope.removeFilter = f => {\r\n $scope.binding.search.filters.remove(f);\r\n // $scope.availableFilters.push(f);\r\n f.values = (f.control == eFilterControl.multiSelect? []: [null]);\r\n $scope.reload();\r\n };\r\n $scope.toggleFilters = () => {\r\n $scope.binding.search.enabled = !$scope.binding.search.enabled;\r\n $scope.reload();\r\n };\r\n $scope.sort = sortColumn => {\r\n if (sortColumn.sortable) {\r\n $scope.columns.forEach(col => {\r\n if (col.field != sortColumn.field) {\r\n col.sorted = false;\r\n col.descending = false;\r\n } else {\r\n if (!col.sorted) {\r\n col.sorted = true;\r\n col.descending = false;\r\n } else {\r\n if (col.descending) {\r\n col.sorted = false;\r\n col.descending = false;\r\n } else {\r\n col.sorted = true;\r\n col.descending = true;\r\n }\r\n }\r\n\r\n if (col.sorted) {\r\n $scope.binding.search.sortField = col.field;\r\n $scope.binding.search.descending = col.descending;\r\n } else {\r\n $scope.binding.search.sortField = null;\r\n $scope.binding.search.descending = false;\r\n }\r\n }\r\n });\r\n\r\n lastLength = 0;\r\n lastRetrieved = 0;\r\n\r\n $scope.reload();\r\n }\r\n };\r\n $scope.modelTypeChange = (modelType) => {\r\n agg.$state.go(modelType.state);\r\n };\r\n\r\n let lastLength = 0;\r\n let lastRetrieved = -1;\r\n $scope.infiniteScroll = () => {\r\n // if the list doesn't have at least the page size of items, it means there's no more\r\n // available, so no need to do another page\r\n let count = $scope.results.length;\r\n lastRetrieved = count == 0 ? -1 : count - lastLength;\r\n let noMore = count > 0 && (count % this.pageSize != 0);\r\n if (!noMore && (lastRetrieved < 0 || lastRetrieved == this.pageSize)) {\r\n lastLength = count;\r\n return $scope.query(true);\r\n }\r\n };\r\n\r\n $scope.reload = (force = false) => {\r\n let search = this.$scope.binding.search;\r\n \r\n let params = this.getQueryStringParams() || {};\r\n if (search.enabled){\r\n params = Object.assign(params, { search: agg.base64Service.encode(JSON.stringify(search)) });\r\n } else {\r\n //create a search without filters\r\n let basicSearch = {\r\n ...search,\r\n filters: []\r\n } as ISavedSearch;\r\n params = Object.assign(params, { search: agg.base64Service.encode(JSON.stringify(basicSearch)) });\r\n }\r\n\r\n let options: TransitionOptions = {};\r\n if (force) options.reload = true;\r\n this.epoch = null;\r\n agg.$state.go(agg.$state.current.name, params, options);\r\n };\r\n\r\n // set all filter sources to an empty array so we have a reference to bind to\r\n $scope.filterSource = {};\r\n for (let p in eFilterSource) $scope.filterSource[p] = [];\r\n\r\n this.filterSourceInfo = {};\r\n for (let e in eFilterSource) this.filterSourceInfo[e] = { valueField: \"id\", labelField: \"name\" };\r\n this.filterSourceInfo[eFilterSource.states] = { valueField: \"value\", labelField: \"label\" };\r\n this.filterSourceInfo[eFilterSource.roles] = { valueField: \"id\", labelField: \"role\" };\r\n this.filterSourceInfo[eFilterSource.manufacturers] = { valueField: null, labelField: null };\r\n this.filterSourceInfo[eFilterSource.enum] = {valueField: \"value\", labelField: \"name\"};\r\n\r\n $scope.editSearch = search => {\r\n this.saveSearchDialog(search);\r\n };\r\n\r\n $scope.deleteSearch = s => {\r\n return agg.api.savedSearches.delete(s.id)\r\n .then(() => $scope.savedSearches.removeWhere(search => search.id == s.id));\r\n };\r\n\r\n $scope.canDeleteSearch = s => {\r\n return this.agg.$rootScope.user.isCompanyAdmin ||\r\n this.agg.$rootScope.user.isAdmin ||\r\n s.createdBy == this.agg.$rootScope.user.id;\r\n };\r\n\r\n $scope.$watch(\"binding.selected\", (newVal, oldVal) => {\r\n if (newVal != oldVal) {\r\n $scope.binding.search = $scope.binding.selected;\r\n //filters need to be re-filled because they are missing $key in saved searches\r\n this.fillFilters();\r\n $scope.reload();\r\n }\r\n });\r\n\r\n\r\n if (!bypassInit) {\r\n this.init();\r\n }\r\n }\r\n protected pageSize = document.body.clientHeight > 1130 ? 42 : 22;\r\n protected epoch: Date = null;\r\n private filterSourceInfo: { [source: string]: { valueField: string; labelField: string; } };\r\n public filledFilterSources: string[] = [];\r\n\r\n /** derived classes must call init. This gives derives classes a chance to fill in scope, etc before things are processed */\r\n public init() {\r\n /**\r\n * could be called in the following ways:\r\n * -no query string: create a new savedSearch and fill it with defaults\r\n * -#search=[base64 encoded json string of the search]\r\n * -#searchId=[the id of the saved search] : call the server with the saved search id\r\n */\r\n if (this.agg.$state.params.search) {\r\n this.$scope.binding.search = JSON.parse(this.agg.base64Service.decode(this.agg.$state.params.search));\r\n this.loadedFromQueryString(this.$scope.binding.search);\r\n } else {\r\n this.$scope.binding.search = this.newSearch();\r\n }\r\n\r\n this.$scope.availableFilters = this.getFiltersFromMeta(this.$scope.binding.search.modelType);\r\n this.$scope.availableFilters.sortBy(f => f.label);\r\n\r\n this.fillFilters();\r\n\r\n this.refreshSavedSearches();\r\n }\r\n\r\n public client(api: ApiService): CrudClient {\r\n throw new Error(\"client() is abstract\");\r\n }\r\n\r\n /**can be overridden to customize the actual call to search api */\r\n public searchCall(args: ISearchArgs, tracker: IPromiseTracker): ng.IPromise {\r\n return this.client(this.agg.api).search(args, tracker);\r\n }\r\n\r\n /**can be overriden to catch when we have just loaded a search via the query string */\r\n public loadedFromQueryString(search: ISavedSearch) {\r\n \r\n }\r\n\r\n /**can be overriden by derived class to provide extra query string params */\r\n public getQueryStringParams(): {}{\r\n return {};\r\n }\r\n /**\r\n * the properties of the queried object that should be returned.\r\n */\r\n public fields(): string[] {\r\n return this.getFieldsFromMeta(this.$scope.binding.search.modelType);\r\n }\r\n\r\n /**\r\n * a new fresh search. Can be overriden by the derived controller\r\n */\r\n public newSearch(): ISavedSearch {\r\n return {\r\n filters: [],\r\n roles: []\r\n };\r\n }\r\n\r\n /** can be overridden by derived class to massage the results before showing them on the screen */\r\n public massageResults(items: T[]) {\r\n \r\n }\r\n\r\n /**\r\n * can be overridden by derived controllers to add a raw filter to the search\r\n */\r\n public getExtraFilters(): IFilter[] {\r\n return [];\r\n }\r\n\r\n /**\r\n * can be overriden by derived controllers to give an extra flag about what we're\r\n * searching (like configured products needs to be set to \"products\" so that the \r\n * search repo knows what we're doing)\r\n */\r\n public getNestedPath(): string {\r\n return null;\r\n }\r\n\r\n /**\r\n * can be overriden by derived controllers to give relative paths to the properties \r\n * of the object described in the nestedPath\r\n */\r\n public nestedFields(): string[] {\r\n return [];\r\n }\r\n\r\n public postProcessFilters(filters: IFilter[]) {\r\n filters.forEach(f => {\r\n if (f.type == eFilterType.attribute) {\r\n let productsScope = this.$scope as any as IProductsScope;\r\n if (productsScope.attributeDb) {\r\n let att = productsScope.attributeDb[f.attributeId];\r\n if (att) {\r\n if (att.type == eAttributeType.number && att.useRangeBuckets) {\r\n if (f.values && f.values.length && f.values[0] != null) { \r\n f.min = f.values[0][\"from\"];\r\n f.max = f.values[0][\"to\"];\r\n }\r\n }\r\n }\r\n }\r\n }\r\n });\r\n }\r\n\r\n protected getSortInfo(): {sortField: string, descending: boolean} {\r\n let ret = { sortField: this.$scope.binding.search.sortField, descending: this.$scope.binding.search.descending };\r\n \r\n //calculate sort\r\n let s = this.$scope.binding.search;\r\n if (s.enabled) {\r\n let sortFilter = s.filters.find(f => f.type == eFilterType.sort);\r\n if (sortFilter && sortFilter.values != null && sortFilter.values.length > 0 && sortFilter.values[0]) {\r\n if (sortFilter.sourceType == eFilterSource.productSorts) {\r\n let v = sortFilter.values[0] as string;\r\n if (v.equalsAny(eProductSortBy.relevance, eProductSortBy.popularity)) {\r\n ret.sortField = \"score\";\r\n ret.descending = true;\r\n } else if (v == eProductSortBy.priceLowToHigh) {\r\n ret.sortField = \"price\";\r\n ret.descending = false;\r\n } else if (v == eProductSortBy.priceHighToLow) {\r\n ret.sortField = \"price\";\r\n ret.descending = true;\r\n } else if (v == eProductSortBy.nameAtoZ) {\r\n ret.sortField = \"name\";\r\n ret.descending = false;\r\n }\r\n }\r\n }\r\n }\r\n\r\n return ret;\r\n }\r\n\r\n public getFieldsFromMeta(modelType: string): string[] {\r\n let m = meta[modelType];\r\n let fields: string[] = [];\r\n for (let prop in m) {\r\n if (prop[0] != \"$\") {\r\n let info: { name: string; type: string; control: string; source: string; default: boolean; } = m[prop];\r\n if (info.type.endsWith(\"[]\")) {\r\n // we look at the array type and get it's meta props\r\n let subFields = this.getFieldsFromMeta(info.type.substr(0, info.type.length - 2));\r\n subFields.forEach(sf => fields.push(info.name + \".\" + sf));\r\n } else {\r\n fields.push(info.name);\r\n }\r\n }\r\n }\r\n return fields;\r\n }\r\n\r\n public getFiltersFromMeta(modelType: string, onlyDefaults?: boolean): IFilter[] {\r\n let m = meta[modelType];\r\n let filters: IFilter[] = [];\r\n for (let prop in m) {\r\n if (prop[0] != \"$\") {\r\n let info: IMetaProperty = m[prop];\r\n if (!info.permissions ||\r\n !info.permissions.length ||\r\n info.permissions.every(p => this.agg.$rootScope.user[\"can\" + p.toPascalCase()])\r\n ) {// check if the current user has permissions to see this filter\r\n if (!info.type.endsWith(\"[]\") &&\r\n info.control != eFilterControl.none &&\r\n (info.default || !onlyDefaults)\r\n ) {\r\n filters.push({\r\n label: loc[\"generic_\" + info.name.toLowerCase() + \"_title\"] ||\r\n loc[m.$name.toLowerCase() + \"_\" + info.name.toLowerCase() + \"_title\"] ||\r\n info.name.toPascalCase(),\r\n type: eFilterType.property,\r\n property: info.name,\r\n sourceType: info.source,\r\n enumType: info.enumType,\r\n control: info.control,\r\n valueField: this.filterSourceInfo[info.source].valueField,\r\n labelField: this.filterSourceInfo[info.source].labelField,\r\n headerField: this.filterSourceInfo[info.source].labelField,\r\n values: (info.control == eFilterControl.multiSelect? []: [null]),\r\n sticky: info.sticky\r\n });\r\n }\r\n }\r\n }\r\n }\r\n return filters;\r\n }\r\n\r\n protected getFilterKey(f: IFilter): string {\r\n let key = f.sourceType;\r\n if (f.attributeId) {\r\n let productsScope = this.$scope as any as IProductsScope;\r\n key = f.sourceType + \"_\" + f.attributeId + \"_\" + productsScope.binding.selectedCategory.id;\r\n } else if (f.sourceType == eFilterSource.enum){\r\n key = f.sourceType + \"_\" + f.enumType;\r\n }\r\n return key;\r\n }\r\n\r\n public fillFilters() { // fills the search filter sources if they haven't already been filled\r\n this.$scope.binding.search.filters.forEach(f => {\r\n let key = this.getFilterKey(f);\r\n f[\"$key\"] = key;\r\n if (!this.filledFilterSources.some(s => s.isEqual(key))) {\r\n this.filledFilterSources.push(key); \r\n if (f.sourceType == eFilterSource.enum){\r\n this.$scope.filterSource[key] = ((this.agg.$filter as any)(\"enum\") as IEnumFilter)(f.enumType, false);\r\n if (f.enumType == \"eJobStatus\"){ // job status is stored as an int in the database\r\n let i = 0;\r\n for(let v of this.$scope.filterSource[key]){\r\n v.value = i;\r\n i++;\r\n }\r\n }\r\n } else if (f.sourceType == eFilterSource.users) {\r\n this.agg.api.users.search({\r\n fields: [\"id\", \"firstName\", \"lastName\", \"name\"], sortField: \"firstName\"\r\n }).then(users => this.$scope.filterSource[key] = users);\r\n } else if (f.sourceType == eFilterSource.states) {\r\n this.agg.api.workflows.states()\r\n .then(r => this.$scope.filterSource[key] = [\r\n {value: null, label: loc.unsubmitted}, \r\n ...r\r\n ]);\r\n } else if (f.sourceType == eFilterSource.properties) {\r\n this.$scope.filterSource[key] = Object.keys(meta[this.$scope.binding.search.modelType + \"Meta\"]);\r\n } else if (f.sourceType == eFilterSource.customers) {\r\n this.$scope.filterSource[key] = this.agg.api.customers\r\n .search({ fields: [\"id\", \"name\"] })\r\n .then(customers => this.$scope.filterSource[key] = [\r\n {id: null, name: loc.none.capitalize()}, \r\n ...customers\r\n ]);\r\n } else if (f.sourceType == eFilterSource.configurators) {\r\n // only get the products this user has the rights to see\r\n this.$scope.filterSource[key] = this.agg.api.products\r\n .searchByCategory({\r\n sortField: \"name\",\r\n fields: [\"id\", \"name\"],\r\n descending: false,\r\n filters: [ProductClient.getIsConfiguredFilter(true)],\r\n take: 500\r\n })\r\n .then(configs => this.$scope.filterSource[key] = [\r\n {\r\n id: null,\r\n name: loc.any\r\n },\r\n ...configs]\r\n );\r\n } else if (f.sourceType == eFilterSource.roles) {\r\n this.$scope.filterSource[key] = this.agg.api.roles\r\n .search({ fields: [\"id\", \"role\"] })\r\n .then(roles => this.$scope.filterSource[key] = roles);\r\n } else if (f.sourceType == eFilterSource.manufacturers) {\r\n this.$scope.filterSource[key] = this.agg.api.products.uniqueValues({ property: meta.Product.manufacturer.name })\r\n .then(manufacturers => this.$scope.filterSource[key] = manufacturers);\r\n } else if (f.sourceType == eFilterSource.suggestQuotes) {\r\n this.$scope.filterSource[key] = q => this.agg.api.quotes.suggest({ query: q, fields: [\"name\"] });\r\n } else if (f.sourceType == eFilterSource.suggestContacts) {\r\n this.$scope.filterSource[key] = q => this.agg.api.contacts.suggest({ query: q, fields: [\"name\"] });\r\n } else if (f.sourceType == eFilterSource.suggestCustomers) {\r\n this.$scope.filterSource[key] = q => this.agg.api.customers.suggest({ query: q, fields: [\"name\"] });\r\n } else if (f.sourceType == eFilterSource.suggestProducts) {\r\n this.$scope.filterSource[key] = q => this.agg.api.products.suggest({ query: q, fields: [\"name\"] });\r\n }else if (f.sourceType == eFilterSource.productSorts) {\r\n this.$scope.filterSource[key] = [\r\n {\r\n value: eProductSortBy.relevance,\r\n label: loc.eproductsortby_relevance_title\r\n }, {\r\n value: eProductSortBy.priceLowToHigh,\r\n label: loc.eproductsortby_pricelowtohigh_title\r\n }, {\r\n value: eProductSortBy.priceHighToLow,\r\n label: loc.eproductsortby_pricehightolow_title\r\n }, {\r\n value: eProductSortBy.popularity,\r\n label: loc.eproductsortby_popularity_title\r\n }, {\r\n value: eProductSortBy.nameAtoZ,\r\n label: loc.eproductsortby_nameatoz_title\r\n }\r\n ];\r\n } else if (f.sourceType == eFilterSource.attributes) {\r\n let productsScope = this.$scope as any as IProductsScope;\r\n let categoryIds = [];\r\n if (productsScope.binding.selectedCategory.id >= 0) {\r\n categoryIds = productsScope.getChildCategories(productsScope.binding.selectedCategory);\r\n }\r\n this.$scope.filterSource[key] = [];\r\n if (productsScope.attributeDb) {\r\n let att = productsScope.attributeDb[f.attributeId];\r\n if (att.type == eAttributeType.number && att.useRangeBuckets) {\r\n this.agg.api.products.attributeRanges({ id: att.id, ranges: att.ranges, categoryIds })\r\n .then(buckets => { \r\n buckets.removeWhere(b => b.count <= 0);\r\n let options: any[] = [];\r\n buckets.forEach(b => {\r\n let label = '';\r\n if (b.from == null) label += \"< \";\r\n if (b.to == null) label += \"> \";\r\n if (b.from != null) label += b.from.toString();\r\n if (b.from != null && b.to != null) label += \" - \";\r\n if (b.to != null) label += b.to.toString();\r\n options.push({ value: b, label: label });\r\n });\r\n this.$scope.filterSource[key].push(...options);\r\n });\r\n } else {\r\n this.agg.api.products.uniqueAttributeValues({ id: att.id, type: att.type, categoryIds })\r\n .then(vals => {\r\n this.$scope.filterSource[key].push(...vals);\r\n //if we are confined to a list, merge with the category attribute options so we can get the images\r\n if (att.confineToList) {\r\n for (let v of vals) {\r\n let o = att.options.find(n => n.value == v.value);\r\n if (o) {\r\n v[\"image\"] = o.image;\r\n }\r\n }\r\n }\r\n });\r\n // if (att.confineToList) {\r\n // this.$scope.filterSource[key].push(...att.options);\r\n // } else {\r\n // this.agg.api.products.uniqueAttributeValues({ id: att.id, type: att.type })\r\n // .then(vals => this.$scope.filterSource[key].push(...vals));\r\n // }\r\n }\r\n }\r\n } else if (f.sourceType == eFilterSource.headerFields) {\r\n this.agg.api.quoteHeaders.searchFields().then(r => {\r\n this.$scope.filterSource[key] = r\r\n });\r\n }\r\n }\r\n });\r\n }\r\n\r\n public uiOnParamsChanged(changedParams, $transition$) {\r\n if ($transition$.options().source == \"url\"){\r\n if (changedParams.search) {\r\n this.$scope.binding.search = JSON.parse(this.agg.base64Service.decode(changedParams.search));\r\n } else {\r\n this.$scope.binding.search = this.newSearch();\r\n }\r\n this.fillSorts(this.$scope.binding.search.sortField, this.$scope.binding.search.descending);\r\n } \r\n this.$scope.query(false); \r\n }\r\n\r\n /** can be overriden to handle what happens after items are deleted */\r\n protected onItemsDeleted(items: T[]) {\r\n \r\n }\r\n\r\n protected deleteItems() {\r\n let selected = this.$scope.results.filter(i => (i as any).$selected);\r\n\r\n if (selected.length > 0) {\r\n this.agg.dialogService.dialog({\r\n content: loc.msg_confirmdelete,\r\n buttons: [\r\n new DialogButton(loc.ok, icons.success, args => {\r\n let tracker = this.agg.$rootScope.contentTracker;\r\n let promises: ng.IPromise[] = [];\r\n\r\n selected.forEach(item => {\r\n let promise = this.client(this.agg.api).delete((item as any).id, null, true);\r\n tracker.addPromise(promise);\r\n promises.push(promise);\r\n });\r\n\r\n this.agg.$q.all(promises).then(() => {\r\n this.onItemsDeleted(selected);\r\n }).finally(() => {\r\n this.$scope.reload(true);\r\n });\r\n }),\r\n new DialogButton(loc.cancel, icons.cancel, args => { })\r\n ]\r\n });\r\n }\r\n }\r\n\r\n protected clone() {\r\n let selected = this.$scope.results.filter(i => (i as any).$selected);\r\n let promises: ng.IPromise[] = [];\r\n selected.forEach(item => {\r\n let promise = this.client(this.agg.api).clone((item as any).id);\r\n this.agg.$rootScope.contentTracker.addPromise(promise);\r\n promises.push(promise);\r\n });\r\n\r\n this.agg.$q.all(promises).then(() => this.$scope.reload(true));\r\n }\r\n\r\n protected refreshSavedSearches() {\r\n if (this.$scope.savedSearchEnabled) {\r\n return this.agg.api.savedSearches.mySearches(this.$scope.binding.search.modelType).then(r => this.$scope.savedSearches = r);\r\n }\r\n }\r\n\r\n protected saveSearchDialog(search: ISavedSearch) {\r\n search = search || this.$scope.binding.search;\r\n let dscope: ISaveSearchDialogScope = this.agg.$rootScope.$new();\r\n if (this.agg.$rootScope.user.isCompanyAdmin || this.agg.$rootScope.user.isAdmin) {\r\n this.agg.api.roles.search({ take: 1000, sortField: \"role\" }).then(r => dscope.roles = r);\r\n }\r\n dscope.model = { name: \"New Search\", roles: search.roles || [] };\r\n\r\n this.agg.dialogService.dialog({\r\n template: Dirs.view(\"dialog-save-search\"),\r\n scope: dscope,\r\n buttons: [\r\n new DialogButton(loc.ok, icons.success, args => {\r\n // validate there is a name\r\n if (!dscope.model.name) {\r\n dscope.validation.name = \"Name is required\";\r\n args.close = false;\r\n return;\r\n }\r\n let newSearch = Object.assign({}, search); // create a new search\r\n newSearch.id = null; // clear out the id so it's treated as an insert\r\n newSearch.name = dscope.model.name;\r\n newSearch.roles = dscope.model.roles;\r\n \r\n this.agg.api.savedSearches.insert(newSearch, this.agg.$rootScope.contentTracker).then(r => {\r\n this.refreshSavedSearches().then(() => {\r\n this.$scope.binding.selected = this.$scope.savedSearches.find(ss => ss.id == r.id);\r\n });\r\n });\r\n }),\r\n new DialogButton(loc.close, icons.cancel, args => { })\r\n ]\r\n });\r\n }\r\n\r\n protected fillSorts(sortColumnName: string, descending: boolean){\r\n for(let col of this.$scope.columns){\r\n if (!sortColumnName || col.field != sortColumnName) {\r\n col.sorted = false;\r\n col.descending = false;\r\n } else {\r\n col.sorted = true;\r\n col.descending = descending;\r\n }\r\n }\r\n }\r\n}\r\n","import { NgView } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { ApiService } from \"@app/services/api.service\";\r\nimport { SearchService } from \"@app/services/search.service\";\r\nimport { ISearchScope, SearchController } from \"@app/views/search.view\";\r\nimport { IContact, ISavedSearch, meta } from \"@models\";\r\nimport { icons } from \"@tools\";\r\n\r\nexport interface IContactsScope extends ISearchScope {\r\n\r\n}\r\n\r\n@NgView({\r\n token: Token.ContactsView,\r\n inherit: [Token.SearchView]\r\n})\r\nexport class ContactsController extends SearchController {\r\n constructor(\r\n $scope: IContactsScope,\r\n agg: SearchService) {\r\n\r\n super(\r\n $scope,\r\n agg\r\n );\r\n\r\n agg.drawerService.pageTitle = loc.contacts;\r\n agg.drawerService.pageIcon = icons.user;\r\n\r\n agg.drawerService.setHelpUrl(\"Contacts\");\r\n\r\n if (agg.$rootScope.user.canModifyCustomers) {\r\n agg.drawerService.addDrawer(icons.add, loc.add, () => agg.$state.go(\"kb.contactNew\"));\r\n agg.drawerService.addDrawer(icons.clone, loc.clone, () => this.clone());\r\n agg.drawerService.addDrawer(icons.deleter, loc.deleter, () => this.deleteItems());\r\n }\r\n }\r\n\r\n public client(api: ApiService) {\r\n return api.contacts;\r\n }\r\n\r\n public newSearch(): ISavedSearch {\r\n return {\r\n modelType: meta.Contact.$name,\r\n sortField: \"FirstName\",\r\n descending: false,\r\n filters: this.getFiltersFromMeta(meta.Contact.$name, true),\r\n roles: []\r\n };\r\n }\r\n}\r\n","import { NgView } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { ApiService } from \"@app/services/api.service\";\r\nimport { CrudService } from \"@app/services/crud.service\";\r\nimport { CrudController, ICrudScope } from \"@app/views/crud.view\";\r\nimport { eViewType, ICustomer } from \"@models\";\r\nimport { icons } from \"@tools\";\r\n\r\nexport interface ICustomerScope extends ICrudScope {\r\n customerTypes: string[];\r\n}\r\n\r\n@NgView({\r\n token: Token.CustomerView,\r\n inherit: [Token.CrudView]\r\n})\r\nexport class CustomerController extends CrudController {\r\n constructor(\r\n public $scope: ICustomerScope,\r\n crudService: CrudService,\r\n model: ICustomer\r\n ) {\r\n\r\n super(\r\n $scope,\r\n crudService,\r\n model);\r\n\r\n this.drawerService.setHelpUrl(\"Customers\");\r\n\r\n let viewType = this.$state.current.data.viewType;\r\n\r\n if ($scope.model) {\r\n this.deleteMsg = loc.msg_deleterecord.format(loc.customer_title, $scope.model.name);\r\n }\r\n\r\n if (viewType == eViewType.new) {\r\n\r\n $scope.model = {\r\n idCompany: this.$rootScope.company.id,\r\n name: \"New Customer\",\r\n shipToBillingAddress: true,\r\n type: loc.customer_type_direct\r\n } as any;\r\n }\r\n\r\n // customerTypes\r\n this.$http.get(\"/api/customers/types\").then(response => {\r\n $scope.customerTypes = response.data;\r\n });\r\n\r\n // add drawers\r\n if ($scope.isEdit || $scope.isNew) {\r\n let drDelete = this.drawerService.addDrawer(icons.deleter, loc.deleter, $scope.delete, $scope.isEdit);\r\n let drSave = this.drawerService.addDrawer(icons.save, loc.save, $scope.save);\r\n let drCancel = this.drawerService.addDrawer(icons.cancel, loc.cancel, $scope.cancel);\r\n } else {\r\n let drEdit = this.drawerService.addDrawer(icons.edit, loc.edit, () => {\r\n this.$state.go(\"kb.admin.customerEdit\", { id: $scope.model.id });\r\n }, this.$rootScope.user.canModifyCustomers);\r\n let drDelete = this.drawerService.addDrawer(\r\n icons.deleter,\r\n loc.deleter,\r\n $scope.delete,\r\n this.$rootScope.user.canModifyCustomers\r\n );\r\n }\r\n\r\n }\r\n\r\n public client(api: ApiService) {\r\n return api.customers;\r\n }\r\n\r\n public waitForRefresh() {\r\n return true;\r\n }\r\n\r\n public onSuccess() {\r\n this.$state.go(\"kb.customers\");\r\n }\r\n\r\n public onDelete() {\r\n this.$state.go(\"kb.customers\");\r\n }\r\n}\r\n","import { NgView } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { ApiService } from \"@app/services/api.service\";\r\nimport { SearchService } from \"@app/services/search.service\";\r\nimport { ISearchScope, SearchController } from \"@app/views/search.view\";\r\nimport { ICustomer, ISavedSearch, meta } from \"@models\";\r\nimport { icons } from \"@tools\";\r\n\r\nexport interface ICustomersScope extends ISearchScope {\r\n fixUrl: (url: string) => string;\r\n}\r\n\r\n@NgView({\r\n token: Token.CustomersView,\r\n inherit: [Token.SearchView]\r\n})\r\nexport class CustomersController extends SearchController {\r\n constructor(\r\n $scope: ICustomersScope,\r\n agg: SearchService\r\n ) {\r\n\r\n super(\r\n $scope,\r\n agg\r\n );\r\n\r\n agg.drawerService.pageTitle = loc.customers;\r\n agg.drawerService.pageIcon = icons.users;\r\n\r\n agg.drawerService.setHelpUrl(\"Customers\");\r\n\r\n if (agg.$rootScope.user.canModifyCustomers) {\r\n agg.drawerService.addDrawer(icons.add, loc.add, () => agg.$state.go(\"kb.customerNew\"));\r\n agg.drawerService.addDrawer(icons.clone, loc.clone, () => this.clone());\r\n agg.drawerService.addDrawer(icons.deleter, loc.deleter, () => this.deleteItems());\r\n }\r\n \r\n $scope.fixUrl = url => {\r\n if (url && !url.startsWith(\"http\")) url = \"http://\" + url;\r\n return url;\r\n };\r\n }\r\n \r\n public client(api: ApiService) {\r\n return api.customers;\r\n }\r\n\r\n public newSearch(): ISavedSearch {\r\n return {\r\n modelType: meta.Customer.$name,\r\n sortField: \"name\",\r\n descending: false,\r\n filters: this.getFiltersFromMeta(meta.Customer.$name, true),\r\n roles: []\r\n };\r\n }\r\n}\r\n","import { NgView } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { DialogService } from \"@app/services/dialog.service\";\r\nimport { BaseController } from \"@app/views/base.view\";\r\nimport { IAlert, IDialog } from \"@models\";\r\n\r\nexport interface IDialogModel {\r\n alerts: IAlert[];\r\n dialogs: IDialog[];\r\n}\r\n\r\nexport interface IDialogViewScope extends ng.IScope {\r\n model: IDialogModel;\r\n closeAlert: (index: number) => void;\r\n}\r\n\r\n@NgView({\r\n token: Token.DialogView,\r\n dependencies: [\r\n Token.$Scope,\r\n Token.DialogService,\r\n ]\r\n})\r\nexport class DialogController extends BaseController {\r\n\r\n constructor(\r\n public $scope: IDialogViewScope,\r\n public dialogService: DialogService\r\n ) {\r\n\r\n super();\r\n\r\n $scope.model = {\r\n alerts: dialogService.alerts,\r\n dialogs: dialogService.dialogs\r\n };\r\n\r\n $scope.closeAlert = index => {\r\n dialogService.closeAlert(index);\r\n };\r\n }\r\n}\r\n","import { NgView } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { ApiService } from \"@app/services/api.service\";\r\nimport { SearchService } from \"@app/services/search.service\";\r\nimport { ISearchScope, SearchController } from \"@app/views/search.view\";\r\nimport { INotification, ISavedSearch, meta } from \"@models\";\r\nimport { icons } from \"@tools\";\r\n\r\nexport interface INotificationsScope extends ISearchScope {\r\n fixUrl: (url: string) => string;\r\n}\r\n\r\n@NgView({\r\n token: Token.NotificationsView,\r\n inherit: [Token.SearchView]\r\n})\r\nexport class NotificationsController extends SearchController {\r\n constructor(\r\n $scope: INotificationsScope,\r\n agg: SearchService\r\n ) {\r\n\r\n super(\r\n $scope,\r\n agg\r\n );\r\n\r\n $scope.allowSearch = false;\r\n agg.drawerService.pageTitle = loc.notifications;\r\n agg.drawerService.pageIcon = icons.email;\r\n\r\n agg.drawerService.setHelpUrl(\"Notifications\");\r\n }\r\n\r\n public client(api: ApiService) {\r\n return api.notifications;\r\n }\r\n\r\n public newSearch(): ISavedSearch {\r\n return {\r\n modelType: meta.Notification.$name,\r\n sortField: \"createdDate\",\r\n descending: true,\r\n filters: this.getFiltersFromMeta(meta.Notification.$name, true),\r\n roles: []\r\n };\r\n }\r\n}\r\n","import { BaseController } from \"@app/views/base.view\";\r\nimport { Utils } from \"@tools\";\r\nimport { NgView } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { DrawerService } from \"@app/services/drawer.service\";\r\n\r\nexport interface IDrawerScope extends ng.IScope {\r\n drawerService: DrawerService;\r\n}\r\n\r\n@NgView({\r\n token: Token.DrawerView,\r\n dependencies: [\r\n Token.$Scope,\r\n Token.DrawerService,\r\n Token.$Timeout,\r\n ]\r\n})\r\nexport class DrawerController extends BaseController {\r\n\r\n constructor(\r\n public $scope: IDrawerScope,\r\n public drawerService: DrawerService,\r\n $timeout: ng.ITimeoutService\r\n ) {\r\n\r\n super();\r\n\r\n $scope.drawerService = drawerService;\r\n\r\n // routine for resizing drawer buttons if there are too many\r\n let resizeDrawer = Utils.throttle(() => {\r\n let $drawerButtons = jQuery(\".kb-drawer__buttons\");\r\n let totalWidth: number;\r\n $drawerButtons.find(\".kb-drawer__button\").each((i, e) => {\r\n totalWidth += jQuery(e).outerWidth();\r\n });\r\n\r\n $drawerButtons.toggleClass(\"is-icons-only\", totalWidth > $drawerButtons.innerWidth());\r\n }, 100);\r\n\r\n $scope.$watchCollection(\"drawerService.drawers\", () => {\r\n resizeDrawer();\r\n });\r\n\r\n // track the window size\r\n jQuery(window).resize(() => {\r\n resizeDrawer();\r\n });\r\n }\r\n}\r\n","import { NgView } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { AuthService } from \"@app/services/auth.service\";\r\nimport { QuoteService } from \"@app/services/quote.service\";\r\nimport { SfdcService } from \"@app/services/sfdc.service\";\r\nimport { CrudService } from \"@app/services/crud.service\";\r\nimport { SignalrService } from \"@app/services/signalr.service\";\r\nimport { StorageService } from \"@app/services/storage.service\";\r\nimport { eEnvironment, INotification, IPagedResult, IPendingApproval, IQuote, IRootScope } from \"@models\";\r\nimport { events } from \"@tools\";\r\n\r\nexport interface IPortalModel {\r\n quote?: IQuote;\r\n mobileMenuVisible?: boolean;\r\n}\r\n\r\nexport interface IPortalScope extends ng.IScope {\r\n model: IPortalModel;\r\n sfdcService: SfdcService;\r\n\r\n logout: () => void;\r\n login: () => void;\r\n companySubdomains: string[];\r\n browseToSubdomain: (subdomain: string) => void;\r\n environments: string[];\r\n browseToEnvironment: (env: string) => void;\r\n\r\n showMobileMenu: () => void;\r\n hideMobileMenu: () => void;\r\n goToQuote: () => void;\r\n mobileKeyboard: boolean; // tracks whether a mobile keyboard is being shown\r\n readNotification: (notification: INotification, navigate?: boolean) => void;\r\n markAllNotificationsAsRead: () => void;\r\n notifications: INotification[];\r\n pendingApprovals: IPendingApproval[];\r\n\r\n newNotificationCount: () => number;\r\n}\r\n\r\n@NgView({\r\n token: Token.PortalView,\r\n dependencies: [\r\n Token.$Scope,\r\n Token.$Http,\r\n Token.AuthService,\r\n Token.$RootScope,\r\n Token.$Window,\r\n Token.QuoteService,\r\n Token.$Location,\r\n Token.SignalRService,\r\n Token.SfdcService,\r\n Token.StorageService,\r\n Token.CrudService\r\n ]\r\n})\r\nexport class PortalController {\r\n constructor(\r\n private $scope: IPortalScope,\r\n private $http: ng.IHttpService,\r\n private authService: AuthService,\r\n private $rootScope: IRootScope,\r\n private $window: ng.IWindowService,\r\n private quoteService: QuoteService,\r\n private $location: ng.ILocationService,\r\n private signalrService: SignalrService,\r\n private sfdcService: SfdcService,\r\n private storageService: StorageService,\r\n private agg: CrudService\r\n ) {\r\n\r\n\r\n $scope.model = {};\r\n $scope.notifications = [];\r\n $scope.pendingApprovals = [];\r\n $scope.sfdcService = sfdcService;\r\n\r\n $scope.$watch(() => quoteService.quote, opp => {\r\n $scope.model.quote = opp;\r\n });\r\n\r\n $scope.goToQuote = () => {\r\n quoteService.goToQuote();\r\n };\r\n\r\n $scope.login = () => {\r\n $rootScope.user = null;\r\n $rootScope.$broadcast(events.loginRequested);\r\n };\r\n\r\n $scope.logout = () => {\r\n authService.logout();\r\n };\r\n\r\n $scope.showMobileMenu = () => {\r\n $scope.model.mobileMenuVisible = true;\r\n };\r\n\r\n $scope.hideMobileMenu = () => {\r\n $scope.model.mobileMenuVisible = false;\r\n };\r\n\r\n let refreshNotifications = () => {\r\n $http.get>(\r\n \"/api/notifications\",\r\n {\r\n params: { pageSize: 10 },\r\n ignoreSecurity: true\r\n }\r\n ).then(r => {\r\n $scope.notifications.clear();\r\n $scope.notifications.pushArray(r.data.items);\r\n });\r\n };\r\n\r\n let onNotificationSignal = () => {\r\n\r\n // fill in notifications\r\n refreshNotifications();\r\n };\r\n\r\n let offOnLogin = $rootScope.$on(events.loginSuccessful, () => {\r\n if ($rootScope.user.id != -1) {\r\n this.signalrService.notificationInvoke(\r\n \"subscribe\",\r\n this.$rootScope.company.uniqueName,\r\n this.$rootScope.user.id\r\n );\r\n this.signalrService.notificationOn(\"notification\", onNotificationSignal);\r\n }\r\n });\r\n\r\n $scope.$on(\"$destroy\", () => {\r\n offOnLogin();\r\n if ($rootScope.user.id != -1) {\r\n this.signalrService.notificationInvoke(\r\n \"unsubscribe\",\r\n this.$rootScope.company.uniqueName,\r\n this.$rootScope.user.id\r\n );\r\n this.signalrService.notificationOff(\"notification\", onNotificationSignal);\r\n }\r\n });\r\n\r\n authService.authPromise.then(() => {\r\n // fill in company subdomains to drive the company selection for admins\r\n if ($rootScope.user.isAdmin) {\r\n $http.get(\"/api/companies/subdomains\").then(r => {\r\n $scope.companySubdomains = r.data;\r\n });\r\n }\r\n\r\n $scope.browseToSubdomain = subdomain => {\r\n let segments = $window.location.host.split(\".\");\r\n $window.location.href = \"https://\" + subdomain + \".\" + segments[1] + \".\" + segments[2];\r\n };\r\n\r\n if ($rootScope.user.id != -1) {\r\n // fill in pending approvals\r\n $http.get>(\r\n \"/api/pendingapprovals\",\r\n {\r\n params: { pageSize: 4 },\r\n ignoreSecurity: true\r\n }\r\n ).then(r => {\r\n $scope.pendingApprovals.pushArray(r.data.items);\r\n });\r\n\r\n // fill in notifications\r\n refreshNotifications();\r\n }\r\n });\r\n\r\n // fill in environments for environment selector\r\n $scope.environments = [];\r\n $scope.environments.push(eEnvironment.dev);\r\n $scope.environments.push(eEnvironment.test);\r\n $scope.environments.push(eEnvironment.prod);\r\n\r\n $scope.browseToEnvironment = (env: string) => {\r\n if (env == $rootScope.environment) return;\r\n\r\n let envSuffix = \"\";\r\n if (env != eEnvironment.prod) {\r\n envSuffix = \"-\" + env;\r\n }\r\n let segments = $window.location.host.split(\".\");\r\n $window.location.href =\r\n \"https://\" + $rootScope.company.subdomain + envSuffix + \".\" + segments[1] + \".\" + segments[2];\r\n };\r\n\r\n let focusin = e => {\r\n let phase = $rootScope.$$phase;\r\n if (phase == \"$apply\" || phase == \"$digest\") {\r\n $scope.mobileKeyboard = true;\r\n } else {\r\n $scope.$apply(() => {\r\n $scope.mobileKeyboard = true;\r\n });\r\n }\r\n };\r\n\r\n let focusout = e => {\r\n let phase = $rootScope.$$phase;\r\n if (phase == \"$apply\" || phase == \"$digest\") {\r\n $scope.mobileKeyboard = false;\r\n } else {\r\n $scope.$apply(() => {\r\n $scope.mobileKeyboard = false;\r\n });\r\n }\r\n };\r\n $(document).on(\"focusin\", \"input[type='text']\", focusin);\r\n $(document).on(\"focusout\", \"input[type='text']\", focusout);\r\n\r\n $scope.readNotification = (notification, navigate: boolean = true) => {\r\n $http.post(\"/api/notifications/markasread\", [notification.id]);\r\n // mark as read locally too\r\n $scope.notifications.find(n => {\r\n return n.id == notification.id;\r\n }).read = true;\r\n if (navigate) $location.path(notification.urlPath);\r\n };\r\n\r\n $scope.markAllNotificationsAsRead = () => {\r\n $scope.notifications.forEach(n => {\r\n $scope.readNotification(n, false);\r\n });\r\n };\r\n\r\n $scope.newNotificationCount = () => {\r\n return $scope.pendingApprovals.length + $scope.notifications.filter(n => !n.read).length;\r\n };\r\n\r\n $scope.$on(\"$destroy\", () => {\r\n $(document).off(\"focusin\", \"input[type='text']\", focusin);\r\n $(document).off(\"focusout\", \"input[type='text']\", focusout);\r\n });\r\n\r\n if ($rootScope.context.company.snapStudioMode) {\r\n $rootScope.hideHeader = true;\r\n }\r\n\r\n }\r\n}\r\n","import { BaseController, IBaseScope } from \"@app/views/base.view\";\r\nimport { CrudController } from \"@app/views/crud.view\";\r\nimport { events } from \"@tools\";\r\nimport { NgView } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { IKbUserRegister, IDialogService, eAlertType } from \"@models\";\r\nimport { AuthService, IAuthService } from \"@app/services/auth.service\";\r\nimport { IRootScope } from \"@models\";\r\nimport { ApiService } from \"../..\";\r\n\r\nexport interface IPrivacyPolicy {\r\n agreed?: boolean;\r\n}\r\n\r\nexport interface IPrivacyPolicyScope extends IBaseScope {\r\n privacyPolicyModel: IPrivacyPolicy;\r\n agree: () => void;\r\n logout: () => void;\r\n}\r\n\r\n@NgView({\r\n token: Token.PrivacyPolicyView,\r\n dependencies: [\r\n Token.$Scope,\r\n Token.ApiService,\r\n Token.$RootScope,\r\n Token.DialogService,\r\n Token.AuthService\r\n ]\r\n})\r\nexport class PrivacyPolicyController extends BaseController {\r\n constructor(\r\n private $scope: IPrivacyPolicyScope,\r\n private api: ApiService,\r\n private $rootScope: IRootScope,\r\n private dialogService: IDialogService,\r\n private authService: IAuthService\r\n ) {\r\n\r\n super();\r\n $scope.privacyPolicyModel = {};\r\n\r\n\r\n\r\n $scope.logout = () => {\r\n authService.logout();\r\n };\r\n\r\n $scope.agree = () => {\r\n if (!$scope.privacyPolicyModel.agreed) {\r\n dialogService.alert({\r\n msg: \"Before you can continue you must agree to the privacy policy.\",\r\n type: eAlertType.error,\r\n persist: true\r\n });\r\n return;\r\n }\r\n this.api.users.acceptPrivacyPolicy().then((u) => {\r\n $rootScope.user.hasLatestPrivacyPolicy = true;\r\n });\r\n };\r\n }\r\n}\r\n","// can-promise has a crash in some versions of react native that dont have\n// standard global objects\n// https://github.com/soldair/node-qrcode/issues/157\n\nmodule.exports = function () {\n return typeof Promise === 'function' && Promise.prototype && Promise.prototype.then\n}\n","let toSJISFunction\nconst CODEWORDS_COUNT = [\n 0, // Not used\n 26, 44, 70, 100, 134, 172, 196, 242, 292, 346,\n 404, 466, 532, 581, 655, 733, 815, 901, 991, 1085,\n 1156, 1258, 1364, 1474, 1588, 1706, 1828, 1921, 2051, 2185,\n 2323, 2465, 2611, 2761, 2876, 3034, 3196, 3362, 3532, 3706\n]\n\n/**\n * Returns the QR Code size for the specified version\n *\n * @param {Number} version QR Code version\n * @return {Number} size of QR code\n */\nexports.getSymbolSize = function getSymbolSize (version) {\n if (!version) throw new Error('\"version\" cannot be null or undefined')\n if (version < 1 || version > 40) throw new Error('\"version\" should be in range from 1 to 40')\n return version * 4 + 17\n}\n\n/**\n * Returns the total number of codewords used to store data and EC information.\n *\n * @param {Number} version QR Code version\n * @return {Number} Data length in bits\n */\nexports.getSymbolTotalCodewords = function getSymbolTotalCodewords (version) {\n return CODEWORDS_COUNT[version]\n}\n\n/**\n * Encode data with Bose-Chaudhuri-Hocquenghem\n *\n * @param {Number} data Value to encode\n * @return {Number} Encoded value\n */\nexports.getBCHDigit = function (data) {\n let digit = 0\n\n while (data !== 0) {\n digit++\n data >>>= 1\n }\n\n return digit\n}\n\nexports.setToSJISFunction = function setToSJISFunction (f) {\n if (typeof f !== 'function') {\n throw new Error('\"toSJISFunc\" is not a valid function.')\n }\n\n toSJISFunction = f\n}\n\nexports.isKanjiModeEnabled = function () {\n return typeof toSJISFunction !== 'undefined'\n}\n\nexports.toSJIS = function toSJIS (kanji) {\n return toSJISFunction(kanji)\n}\n","exports.L = { bit: 1 }\nexports.M = { bit: 0 }\nexports.Q = { bit: 3 }\nexports.H = { bit: 2 }\n\nfunction fromString (string) {\n if (typeof string !== 'string') {\n throw new Error('Param is not a string')\n }\n\n const lcStr = string.toLowerCase()\n\n switch (lcStr) {\n case 'l':\n case 'low':\n return exports.L\n\n case 'm':\n case 'medium':\n return exports.M\n\n case 'q':\n case 'quartile':\n return exports.Q\n\n case 'h':\n case 'high':\n return exports.H\n\n default:\n throw new Error('Unknown EC Level: ' + string)\n }\n}\n\nexports.isValid = function isValid (level) {\n return level && typeof level.bit !== 'undefined' &&\n level.bit >= 0 && level.bit < 4\n}\n\nexports.from = function from (value, defaultValue) {\n if (exports.isValid(value)) {\n return value\n }\n\n try {\n return fromString(value)\n } catch (e) {\n return defaultValue\n }\n}\n","function BitBuffer () {\n this.buffer = []\n this.length = 0\n}\n\nBitBuffer.prototype = {\n\n get: function (index) {\n const bufIndex = Math.floor(index / 8)\n return ((this.buffer[bufIndex] >>> (7 - index % 8)) & 1) === 1\n },\n\n put: function (num, length) {\n for (let i = 0; i < length; i++) {\n this.putBit(((num >>> (length - i - 1)) & 1) === 1)\n }\n },\n\n getLengthInBits: function () {\n return this.length\n },\n\n putBit: function (bit) {\n const bufIndex = Math.floor(this.length / 8)\n if (this.buffer.length <= bufIndex) {\n this.buffer.push(0)\n }\n\n if (bit) {\n this.buffer[bufIndex] |= (0x80 >>> (this.length % 8))\n }\n\n this.length++\n }\n}\n\nmodule.exports = BitBuffer\n","/**\n * Helper class to handle QR Code symbol modules\n *\n * @param {Number} size Symbol size\n */\nfunction BitMatrix (size) {\n if (!size || size < 1) {\n throw new Error('BitMatrix size must be defined and greater than 0')\n }\n\n this.size = size\n this.data = new Uint8Array(size * size)\n this.reservedBit = new Uint8Array(size * size)\n}\n\n/**\n * Set bit value at specified location\n * If reserved flag is set, this bit will be ignored during masking process\n *\n * @param {Number} row\n * @param {Number} col\n * @param {Boolean} value\n * @param {Boolean} reserved\n */\nBitMatrix.prototype.set = function (row, col, value, reserved) {\n const index = row * this.size + col\n this.data[index] = value\n if (reserved) this.reservedBit[index] = true\n}\n\n/**\n * Returns bit value at specified location\n *\n * @param {Number} row\n * @param {Number} col\n * @return {Boolean}\n */\nBitMatrix.prototype.get = function (row, col) {\n return this.data[row * this.size + col]\n}\n\n/**\n * Applies xor operator at specified location\n * (used during masking process)\n *\n * @param {Number} row\n * @param {Number} col\n * @param {Boolean} value\n */\nBitMatrix.prototype.xor = function (row, col, value) {\n this.data[row * this.size + col] ^= value\n}\n\n/**\n * Check if bit at specified location is reserved\n *\n * @param {Number} row\n * @param {Number} col\n * @return {Boolean}\n */\nBitMatrix.prototype.isReserved = function (row, col) {\n return this.reservedBit[row * this.size + col]\n}\n\nmodule.exports = BitMatrix\n","/**\n * Alignment pattern are fixed reference pattern in defined positions\n * in a matrix symbology, which enables the decode software to re-synchronise\n * the coordinate mapping of the image modules in the event of moderate amounts\n * of distortion of the image.\n *\n * Alignment patterns are present only in QR Code symbols of version 2 or larger\n * and their number depends on the symbol version.\n */\n\nconst getSymbolSize = require('./utils').getSymbolSize\n\n/**\n * Calculate the row/column coordinates of the center module of each alignment pattern\n * for the specified QR Code version.\n *\n * The alignment patterns are positioned symmetrically on either side of the diagonal\n * running from the top left corner of the symbol to the bottom right corner.\n *\n * Since positions are simmetrical only half of the coordinates are returned.\n * Each item of the array will represent in turn the x and y coordinate.\n * @see {@link getPositions}\n *\n * @param {Number} version QR Code version\n * @return {Array} Array of coordinate\n */\nexports.getRowColCoords = function getRowColCoords (version) {\n if (version === 1) return []\n\n const posCount = Math.floor(version / 7) + 2\n const size = getSymbolSize(version)\n const intervals = size === 145 ? 26 : Math.ceil((size - 13) / (2 * posCount - 2)) * 2\n const positions = [size - 7] // Last coord is always (size - 7)\n\n for (let i = 1; i < posCount - 1; i++) {\n positions[i] = positions[i - 1] - intervals\n }\n\n positions.push(6) // First coord is always 6\n\n return positions.reverse()\n}\n\n/**\n * Returns an array containing the positions of each alignment pattern.\n * Each array's element represent the center point of the pattern as (x, y) coordinates\n *\n * Coordinates are calculated expanding the row/column coordinates returned by {@link getRowColCoords}\n * and filtering out the items that overlaps with finder pattern\n *\n * @example\n * For a Version 7 symbol {@link getRowColCoords} returns values 6, 22 and 38.\n * The alignment patterns, therefore, are to be centered on (row, column)\n * positions (6,22), (22,6), (22,22), (22,38), (38,22), (38,38).\n * Note that the coordinates (6,6), (6,38), (38,6) are occupied by finder patterns\n * and are not therefore used for alignment patterns.\n *\n * let pos = getPositions(7)\n * // [[6,22], [22,6], [22,22], [22,38], [38,22], [38,38]]\n *\n * @param {Number} version QR Code version\n * @return {Array} Array of coordinates\n */\nexports.getPositions = function getPositions (version) {\n const coords = []\n const pos = exports.getRowColCoords(version)\n const posLength = pos.length\n\n for (let i = 0; i < posLength; i++) {\n for (let j = 0; j < posLength; j++) {\n // Skip if position is occupied by finder patterns\n if ((i === 0 && j === 0) || // top-left\n (i === 0 && j === posLength - 1) || // bottom-left\n (i === posLength - 1 && j === 0)) { // top-right\n continue\n }\n\n coords.push([pos[i], pos[j]])\n }\n }\n\n return coords\n}\n","const getSymbolSize = require('./utils').getSymbolSize\nconst FINDER_PATTERN_SIZE = 7\n\n/**\n * Returns an array containing the positions of each finder pattern.\n * Each array's element represent the top-left point of the pattern as (x, y) coordinates\n *\n * @param {Number} version QR Code version\n * @return {Array} Array of coordinates\n */\nexports.getPositions = function getPositions (version) {\n const size = getSymbolSize(version)\n\n return [\n // top-left\n [0, 0],\n // top-right\n [size - FINDER_PATTERN_SIZE, 0],\n // bottom-left\n [0, size - FINDER_PATTERN_SIZE]\n ]\n}\n","/**\n * Data mask pattern reference\n * @type {Object}\n */\nexports.Patterns = {\n PATTERN000: 0,\n PATTERN001: 1,\n PATTERN010: 2,\n PATTERN011: 3,\n PATTERN100: 4,\n PATTERN101: 5,\n PATTERN110: 6,\n PATTERN111: 7\n}\n\n/**\n * Weighted penalty scores for the undesirable features\n * @type {Object}\n */\nconst PenaltyScores = {\n N1: 3,\n N2: 3,\n N3: 40,\n N4: 10\n}\n\n/**\n * Check if mask pattern value is valid\n *\n * @param {Number} mask Mask pattern\n * @return {Boolean} true if valid, false otherwise\n */\nexports.isValid = function isValid (mask) {\n return mask != null && mask !== '' && !isNaN(mask) && mask >= 0 && mask <= 7\n}\n\n/**\n * Returns mask pattern from a value.\n * If value is not valid, returns undefined\n *\n * @param {Number|String} value Mask pattern value\n * @return {Number} Valid mask pattern or undefined\n */\nexports.from = function from (value) {\n return exports.isValid(value) ? parseInt(value, 10) : undefined\n}\n\n/**\n* Find adjacent modules in row/column with the same color\n* and assign a penalty value.\n*\n* Points: N1 + i\n* i is the amount by which the number of adjacent modules of the same color exceeds 5\n*/\nexports.getPenaltyN1 = function getPenaltyN1 (data) {\n const size = data.size\n let points = 0\n let sameCountCol = 0\n let sameCountRow = 0\n let lastCol = null\n let lastRow = null\n\n for (let row = 0; row < size; row++) {\n sameCountCol = sameCountRow = 0\n lastCol = lastRow = null\n\n for (let col = 0; col < size; col++) {\n let module = data.get(row, col)\n if (module === lastCol) {\n sameCountCol++\n } else {\n if (sameCountCol >= 5) points += PenaltyScores.N1 + (sameCountCol - 5)\n lastCol = module\n sameCountCol = 1\n }\n\n module = data.get(col, row)\n if (module === lastRow) {\n sameCountRow++\n } else {\n if (sameCountRow >= 5) points += PenaltyScores.N1 + (sameCountRow - 5)\n lastRow = module\n sameCountRow = 1\n }\n }\n\n if (sameCountCol >= 5) points += PenaltyScores.N1 + (sameCountCol - 5)\n if (sameCountRow >= 5) points += PenaltyScores.N1 + (sameCountRow - 5)\n }\n\n return points\n}\n\n/**\n * Find 2x2 blocks with the same color and assign a penalty value\n *\n * Points: N2 * (m - 1) * (n - 1)\n */\nexports.getPenaltyN2 = function getPenaltyN2 (data) {\n const size = data.size\n let points = 0\n\n for (let row = 0; row < size - 1; row++) {\n for (let col = 0; col < size - 1; col++) {\n const last = data.get(row, col) +\n data.get(row, col + 1) +\n data.get(row + 1, col) +\n data.get(row + 1, col + 1)\n\n if (last === 4 || last === 0) points++\n }\n }\n\n return points * PenaltyScores.N2\n}\n\n/**\n * Find 1:1:3:1:1 ratio (dark:light:dark:light:dark) pattern in row/column,\n * preceded or followed by light area 4 modules wide\n *\n * Points: N3 * number of pattern found\n */\nexports.getPenaltyN3 = function getPenaltyN3 (data) {\n const size = data.size\n let points = 0\n let bitsCol = 0\n let bitsRow = 0\n\n for (let row = 0; row < size; row++) {\n bitsCol = bitsRow = 0\n for (let col = 0; col < size; col++) {\n bitsCol = ((bitsCol << 1) & 0x7FF) | data.get(row, col)\n if (col >= 10 && (bitsCol === 0x5D0 || bitsCol === 0x05D)) points++\n\n bitsRow = ((bitsRow << 1) & 0x7FF) | data.get(col, row)\n if (col >= 10 && (bitsRow === 0x5D0 || bitsRow === 0x05D)) points++\n }\n }\n\n return points * PenaltyScores.N3\n}\n\n/**\n * Calculate proportion of dark modules in entire symbol\n *\n * Points: N4 * k\n *\n * k is the rating of the deviation of the proportion of dark modules\n * in the symbol from 50% in steps of 5%\n */\nexports.getPenaltyN4 = function getPenaltyN4 (data) {\n let darkCount = 0\n const modulesCount = data.data.length\n\n for (let i = 0; i < modulesCount; i++) darkCount += data.data[i]\n\n const k = Math.abs(Math.ceil((darkCount * 100 / modulesCount) / 5) - 10)\n\n return k * PenaltyScores.N4\n}\n\n/**\n * Return mask value at given position\n *\n * @param {Number} maskPattern Pattern reference value\n * @param {Number} i Row\n * @param {Number} j Column\n * @return {Boolean} Mask value\n */\nfunction getMaskAt (maskPattern, i, j) {\n switch (maskPattern) {\n case exports.Patterns.PATTERN000: return (i + j) % 2 === 0\n case exports.Patterns.PATTERN001: return i % 2 === 0\n case exports.Patterns.PATTERN010: return j % 3 === 0\n case exports.Patterns.PATTERN011: return (i + j) % 3 === 0\n case exports.Patterns.PATTERN100: return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 === 0\n case exports.Patterns.PATTERN101: return (i * j) % 2 + (i * j) % 3 === 0\n case exports.Patterns.PATTERN110: return ((i * j) % 2 + (i * j) % 3) % 2 === 0\n case exports.Patterns.PATTERN111: return ((i * j) % 3 + (i + j) % 2) % 2 === 0\n\n default: throw new Error('bad maskPattern:' + maskPattern)\n }\n}\n\n/**\n * Apply a mask pattern to a BitMatrix\n *\n * @param {Number} pattern Pattern reference number\n * @param {BitMatrix} data BitMatrix data\n */\nexports.applyMask = function applyMask (pattern, data) {\n const size = data.size\n\n for (let col = 0; col < size; col++) {\n for (let row = 0; row < size; row++) {\n if (data.isReserved(row, col)) continue\n data.xor(row, col, getMaskAt(pattern, row, col))\n }\n }\n}\n\n/**\n * Returns the best mask pattern for data\n *\n * @param {BitMatrix} data\n * @return {Number} Mask pattern reference number\n */\nexports.getBestMask = function getBestMask (data, setupFormatFunc) {\n const numPatterns = Object.keys(exports.Patterns).length\n let bestPattern = 0\n let lowerPenalty = Infinity\n\n for (let p = 0; p < numPatterns; p++) {\n setupFormatFunc(p)\n exports.applyMask(p, data)\n\n // Calculate penalty\n const penalty =\n exports.getPenaltyN1(data) +\n exports.getPenaltyN2(data) +\n exports.getPenaltyN3(data) +\n exports.getPenaltyN4(data)\n\n // Undo previously applied mask\n exports.applyMask(p, data)\n\n if (penalty < lowerPenalty) {\n lowerPenalty = penalty\n bestPattern = p\n }\n }\n\n return bestPattern\n}\n","const ECLevel = require('./error-correction-level')\r\n\r\nconst EC_BLOCKS_TABLE = [\r\n// L M Q H\r\n 1, 1, 1, 1,\r\n 1, 1, 1, 1,\r\n 1, 1, 2, 2,\r\n 1, 2, 2, 4,\r\n 1, 2, 4, 4,\r\n 2, 4, 4, 4,\r\n 2, 4, 6, 5,\r\n 2, 4, 6, 6,\r\n 2, 5, 8, 8,\r\n 4, 5, 8, 8,\r\n 4, 5, 8, 11,\r\n 4, 8, 10, 11,\r\n 4, 9, 12, 16,\r\n 4, 9, 16, 16,\r\n 6, 10, 12, 18,\r\n 6, 10, 17, 16,\r\n 6, 11, 16, 19,\r\n 6, 13, 18, 21,\r\n 7, 14, 21, 25,\r\n 8, 16, 20, 25,\r\n 8, 17, 23, 25,\r\n 9, 17, 23, 34,\r\n 9, 18, 25, 30,\r\n 10, 20, 27, 32,\r\n 12, 21, 29, 35,\r\n 12, 23, 34, 37,\r\n 12, 25, 34, 40,\r\n 13, 26, 35, 42,\r\n 14, 28, 38, 45,\r\n 15, 29, 40, 48,\r\n 16, 31, 43, 51,\r\n 17, 33, 45, 54,\r\n 18, 35, 48, 57,\r\n 19, 37, 51, 60,\r\n 19, 38, 53, 63,\r\n 20, 40, 56, 66,\r\n 21, 43, 59, 70,\r\n 22, 45, 62, 74,\r\n 24, 47, 65, 77,\r\n 25, 49, 68, 81\r\n]\r\n\r\nconst EC_CODEWORDS_TABLE = [\r\n// L M Q H\r\n 7, 10, 13, 17,\r\n 10, 16, 22, 28,\r\n 15, 26, 36, 44,\r\n 20, 36, 52, 64,\r\n 26, 48, 72, 88,\r\n 36, 64, 96, 112,\r\n 40, 72, 108, 130,\r\n 48, 88, 132, 156,\r\n 60, 110, 160, 192,\r\n 72, 130, 192, 224,\r\n 80, 150, 224, 264,\r\n 96, 176, 260, 308,\r\n 104, 198, 288, 352,\r\n 120, 216, 320, 384,\r\n 132, 240, 360, 432,\r\n 144, 280, 408, 480,\r\n 168, 308, 448, 532,\r\n 180, 338, 504, 588,\r\n 196, 364, 546, 650,\r\n 224, 416, 600, 700,\r\n 224, 442, 644, 750,\r\n 252, 476, 690, 816,\r\n 270, 504, 750, 900,\r\n 300, 560, 810, 960,\r\n 312, 588, 870, 1050,\r\n 336, 644, 952, 1110,\r\n 360, 700, 1020, 1200,\r\n 390, 728, 1050, 1260,\r\n 420, 784, 1140, 1350,\r\n 450, 812, 1200, 1440,\r\n 480, 868, 1290, 1530,\r\n 510, 924, 1350, 1620,\r\n 540, 980, 1440, 1710,\r\n 570, 1036, 1530, 1800,\r\n 570, 1064, 1590, 1890,\r\n 600, 1120, 1680, 1980,\r\n 630, 1204, 1770, 2100,\r\n 660, 1260, 1860, 2220,\r\n 720, 1316, 1950, 2310,\r\n 750, 1372, 2040, 2430\r\n]\r\n\r\n/**\r\n * Returns the number of error correction block that the QR Code should contain\r\n * for the specified version and error correction level.\r\n *\r\n * @param {Number} version QR Code version\r\n * @param {Number} errorCorrectionLevel Error correction level\r\n * @return {Number} Number of error correction blocks\r\n */\r\nexports.getBlocksCount = function getBlocksCount (version, errorCorrectionLevel) {\r\n switch (errorCorrectionLevel) {\r\n case ECLevel.L:\r\n return EC_BLOCKS_TABLE[(version - 1) * 4 + 0]\r\n case ECLevel.M:\r\n return EC_BLOCKS_TABLE[(version - 1) * 4 + 1]\r\n case ECLevel.Q:\r\n return EC_BLOCKS_TABLE[(version - 1) * 4 + 2]\r\n case ECLevel.H:\r\n return EC_BLOCKS_TABLE[(version - 1) * 4 + 3]\r\n default:\r\n return undefined\r\n }\r\n}\r\n\r\n/**\r\n * Returns the number of error correction codewords to use for the specified\r\n * version and error correction level.\r\n *\r\n * @param {Number} version QR Code version\r\n * @param {Number} errorCorrectionLevel Error correction level\r\n * @return {Number} Number of error correction codewords\r\n */\r\nexports.getTotalCodewordsCount = function getTotalCodewordsCount (version, errorCorrectionLevel) {\r\n switch (errorCorrectionLevel) {\r\n case ECLevel.L:\r\n return EC_CODEWORDS_TABLE[(version - 1) * 4 + 0]\r\n case ECLevel.M:\r\n return EC_CODEWORDS_TABLE[(version - 1) * 4 + 1]\r\n case ECLevel.Q:\r\n return EC_CODEWORDS_TABLE[(version - 1) * 4 + 2]\r\n case ECLevel.H:\r\n return EC_CODEWORDS_TABLE[(version - 1) * 4 + 3]\r\n default:\r\n return undefined\r\n }\r\n}\r\n","const EXP_TABLE = new Uint8Array(512)\nconst LOG_TABLE = new Uint8Array(256)\n/**\n * Precompute the log and anti-log tables for faster computation later\n *\n * For each possible value in the galois field 2^8, we will pre-compute\n * the logarithm and anti-logarithm (exponential) of this value\n *\n * ref {@link https://en.wikiversity.org/wiki/Reed%E2%80%93Solomon_codes_for_coders#Introduction_to_mathematical_fields}\n */\n;(function initTables () {\n let x = 1\n for (let i = 0; i < 255; i++) {\n EXP_TABLE[i] = x\n LOG_TABLE[x] = i\n\n x <<= 1 // multiply by 2\n\n // The QR code specification says to use byte-wise modulo 100011101 arithmetic.\n // This means that when a number is 256 or larger, it should be XORed with 0x11D.\n if (x & 0x100) { // similar to x >= 256, but a lot faster (because 0x100 == 256)\n x ^= 0x11D\n }\n }\n\n // Optimization: double the size of the anti-log table so that we don't need to mod 255 to\n // stay inside the bounds (because we will mainly use this table for the multiplication of\n // two GF numbers, no more).\n // @see {@link mul}\n for (let i = 255; i < 512; i++) {\n EXP_TABLE[i] = EXP_TABLE[i - 255]\n }\n}())\n\n/**\n * Returns log value of n inside Galois Field\n *\n * @param {Number} n\n * @return {Number}\n */\nexports.log = function log (n) {\n if (n < 1) throw new Error('log(' + n + ')')\n return LOG_TABLE[n]\n}\n\n/**\n * Returns anti-log value of n inside Galois Field\n *\n * @param {Number} n\n * @return {Number}\n */\nexports.exp = function exp (n) {\n return EXP_TABLE[n]\n}\n\n/**\n * Multiplies two number inside Galois Field\n *\n * @param {Number} x\n * @param {Number} y\n * @return {Number}\n */\nexports.mul = function mul (x, y) {\n if (x === 0 || y === 0) return 0\n\n // should be EXP_TABLE[(LOG_TABLE[x] + LOG_TABLE[y]) % 255] if EXP_TABLE wasn't oversized\n // @see {@link initTables}\n return EXP_TABLE[LOG_TABLE[x] + LOG_TABLE[y]]\n}\n","const GF = require('./galois-field')\n\n/**\n * Multiplies two polynomials inside Galois Field\n *\n * @param {Uint8Array} p1 Polynomial\n * @param {Uint8Array} p2 Polynomial\n * @return {Uint8Array} Product of p1 and p2\n */\nexports.mul = function mul (p1, p2) {\n const coeff = new Uint8Array(p1.length + p2.length - 1)\n\n for (let i = 0; i < p1.length; i++) {\n for (let j = 0; j < p2.length; j++) {\n coeff[i + j] ^= GF.mul(p1[i], p2[j])\n }\n }\n\n return coeff\n}\n\n/**\n * Calculate the remainder of polynomials division\n *\n * @param {Uint8Array} divident Polynomial\n * @param {Uint8Array} divisor Polynomial\n * @return {Uint8Array} Remainder\n */\nexports.mod = function mod (divident, divisor) {\n let result = new Uint8Array(divident)\n\n while ((result.length - divisor.length) >= 0) {\n const coeff = result[0]\n\n for (let i = 0; i < divisor.length; i++) {\n result[i] ^= GF.mul(divisor[i], coeff)\n }\n\n // remove all zeros from buffer head\n let offset = 0\n while (offset < result.length && result[offset] === 0) offset++\n result = result.slice(offset)\n }\n\n return result\n}\n\n/**\n * Generate an irreducible generator polynomial of specified degree\n * (used by Reed-Solomon encoder)\n *\n * @param {Number} degree Degree of the generator polynomial\n * @return {Uint8Array} Buffer containing polynomial coefficients\n */\nexports.generateECPolynomial = function generateECPolynomial (degree) {\n let poly = new Uint8Array([1])\n for (let i = 0; i < degree; i++) {\n poly = exports.mul(poly, new Uint8Array([1, GF.exp(i)]))\n }\n\n return poly\n}\n","const Polynomial = require('./polynomial')\n\nfunction ReedSolomonEncoder (degree) {\n this.genPoly = undefined\n this.degree = degree\n\n if (this.degree) this.initialize(this.degree)\n}\n\n/**\n * Initialize the encoder.\n * The input param should correspond to the number of error correction codewords.\n *\n * @param {Number} degree\n */\nReedSolomonEncoder.prototype.initialize = function initialize (degree) {\n // create an irreducible generator polynomial\n this.degree = degree\n this.genPoly = Polynomial.generateECPolynomial(this.degree)\n}\n\n/**\n * Encodes a chunk of data\n *\n * @param {Uint8Array} data Buffer containing input data\n * @return {Uint8Array} Buffer containing encoded data\n */\nReedSolomonEncoder.prototype.encode = function encode (data) {\n if (!this.genPoly) {\n throw new Error('Encoder not initialized')\n }\n\n // Calculate EC for this data block\n // extends data size to data+genPoly size\n const paddedData = new Uint8Array(data.length + this.degree)\n paddedData.set(data)\n\n // The error correction codewords are the remainder after dividing the data codewords\n // by a generator polynomial\n const remainder = Polynomial.mod(paddedData, this.genPoly)\n\n // return EC data blocks (last n byte, where n is the degree of genPoly)\n // If coefficients number in remainder are less than genPoly degree,\n // pad with 0s to the left to reach the needed number of coefficients\n const start = this.degree - remainder.length\n if (start > 0) {\n const buff = new Uint8Array(this.degree)\n buff.set(remainder, start)\n\n return buff\n }\n\n return remainder\n}\n\nmodule.exports = ReedSolomonEncoder\n","/**\n * Check if QR Code version is valid\n *\n * @param {Number} version QR Code version\n * @return {Boolean} true if valid version, false otherwise\n */\nexports.isValid = function isValid (version) {\n return !isNaN(version) && version >= 1 && version <= 40\n}\n","const numeric = '[0-9]+'\nconst alphanumeric = '[A-Z $%*+\\\\-./:]+'\nlet kanji = '(?:[u3000-u303F]|[u3040-u309F]|[u30A0-u30FF]|' +\n '[uFF00-uFFEF]|[u4E00-u9FAF]|[u2605-u2606]|[u2190-u2195]|u203B|' +\n '[u2010u2015u2018u2019u2025u2026u201Cu201Du2225u2260]|' +\n '[u0391-u0451]|[u00A7u00A8u00B1u00B4u00D7u00F7])+'\nkanji = kanji.replace(/u/g, '\\\\u')\n\nconst byte = '(?:(?![A-Z0-9 $%*+\\\\-./:]|' + kanji + ')(?:.|[\\r\\n]))+'\n\nexports.KANJI = new RegExp(kanji, 'g')\nexports.BYTE_KANJI = new RegExp('[^A-Z0-9 $%*+\\\\-./:]+', 'g')\nexports.BYTE = new RegExp(byte, 'g')\nexports.NUMERIC = new RegExp(numeric, 'g')\nexports.ALPHANUMERIC = new RegExp(alphanumeric, 'g')\n\nconst TEST_KANJI = new RegExp('^' + kanji + '$')\nconst TEST_NUMERIC = new RegExp('^' + numeric + '$')\nconst TEST_ALPHANUMERIC = new RegExp('^[A-Z0-9 $%*+\\\\-./:]+$')\n\nexports.testKanji = function testKanji (str) {\n return TEST_KANJI.test(str)\n}\n\nexports.testNumeric = function testNumeric (str) {\n return TEST_NUMERIC.test(str)\n}\n\nexports.testAlphanumeric = function testAlphanumeric (str) {\n return TEST_ALPHANUMERIC.test(str)\n}\n","const VersionCheck = require('./version-check')\nconst Regex = require('./regex')\n\n/**\n * Numeric mode encodes data from the decimal digit set (0 - 9)\n * (byte values 30HEX to 39HEX).\n * Normally, 3 data characters are represented by 10 bits.\n *\n * @type {Object}\n */\nexports.NUMERIC = {\n id: 'Numeric',\n bit: 1 << 0,\n ccBits: [10, 12, 14]\n}\n\n/**\n * Alphanumeric mode encodes data from a set of 45 characters,\n * i.e. 10 numeric digits (0 - 9),\n * 26 alphabetic characters (A - Z),\n * and 9 symbols (SP, $, %, *, +, -, ., /, :).\n * Normally, two input characters are represented by 11 bits.\n *\n * @type {Object}\n */\nexports.ALPHANUMERIC = {\n id: 'Alphanumeric',\n bit: 1 << 1,\n ccBits: [9, 11, 13]\n}\n\n/**\n * In byte mode, data is encoded at 8 bits per character.\n *\n * @type {Object}\n */\nexports.BYTE = {\n id: 'Byte',\n bit: 1 << 2,\n ccBits: [8, 16, 16]\n}\n\n/**\n * The Kanji mode efficiently encodes Kanji characters in accordance with\n * the Shift JIS system based on JIS X 0208.\n * The Shift JIS values are shifted from the JIS X 0208 values.\n * JIS X 0208 gives details of the shift coded representation.\n * Each two-byte character value is compacted to a 13-bit binary codeword.\n *\n * @type {Object}\n */\nexports.KANJI = {\n id: 'Kanji',\n bit: 1 << 3,\n ccBits: [8, 10, 12]\n}\n\n/**\n * Mixed mode will contain a sequences of data in a combination of any of\n * the modes described above\n *\n * @type {Object}\n */\nexports.MIXED = {\n bit: -1\n}\n\n/**\n * Returns the number of bits needed to store the data length\n * according to QR Code specifications.\n *\n * @param {Mode} mode Data mode\n * @param {Number} version QR Code version\n * @return {Number} Number of bits\n */\nexports.getCharCountIndicator = function getCharCountIndicator (mode, version) {\n if (!mode.ccBits) throw new Error('Invalid mode: ' + mode)\n\n if (!VersionCheck.isValid(version)) {\n throw new Error('Invalid version: ' + version)\n }\n\n if (version >= 1 && version < 10) return mode.ccBits[0]\n else if (version < 27) return mode.ccBits[1]\n return mode.ccBits[2]\n}\n\n/**\n * Returns the most efficient mode to store the specified data\n *\n * @param {String} dataStr Input data string\n * @return {Mode} Best mode\n */\nexports.getBestModeForData = function getBestModeForData (dataStr) {\n if (Regex.testNumeric(dataStr)) return exports.NUMERIC\n else if (Regex.testAlphanumeric(dataStr)) return exports.ALPHANUMERIC\n else if (Regex.testKanji(dataStr)) return exports.KANJI\n else return exports.BYTE\n}\n\n/**\n * Return mode name as string\n *\n * @param {Mode} mode Mode object\n * @returns {String} Mode name\n */\nexports.toString = function toString (mode) {\n if (mode && mode.id) return mode.id\n throw new Error('Invalid mode')\n}\n\n/**\n * Check if input param is a valid mode object\n *\n * @param {Mode} mode Mode object\n * @returns {Boolean} True if valid mode, false otherwise\n */\nexports.isValid = function isValid (mode) {\n return mode && mode.bit && mode.ccBits\n}\n\n/**\n * Get mode object from its name\n *\n * @param {String} string Mode name\n * @returns {Mode} Mode object\n */\nfunction fromString (string) {\n if (typeof string !== 'string') {\n throw new Error('Param is not a string')\n }\n\n const lcStr = string.toLowerCase()\n\n switch (lcStr) {\n case 'numeric':\n return exports.NUMERIC\n case 'alphanumeric':\n return exports.ALPHANUMERIC\n case 'kanji':\n return exports.KANJI\n case 'byte':\n return exports.BYTE\n default:\n throw new Error('Unknown mode: ' + string)\n }\n}\n\n/**\n * Returns mode from a value.\n * If value is not a valid mode, returns defaultValue\n *\n * @param {Mode|String} value Encoding mode\n * @param {Mode} defaultValue Fallback value\n * @return {Mode} Encoding mode\n */\nexports.from = function from (value, defaultValue) {\n if (exports.isValid(value)) {\n return value\n }\n\n try {\n return fromString(value)\n } catch (e) {\n return defaultValue\n }\n}\n","const Utils = require('./utils')\nconst ECCode = require('./error-correction-code')\nconst ECLevel = require('./error-correction-level')\nconst Mode = require('./mode')\nconst VersionCheck = require('./version-check')\n\n// Generator polynomial used to encode version information\nconst G18 = (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0)\nconst G18_BCH = Utils.getBCHDigit(G18)\n\nfunction getBestVersionForDataLength (mode, length, errorCorrectionLevel) {\n for (let currentVersion = 1; currentVersion <= 40; currentVersion++) {\n if (length <= exports.getCapacity(currentVersion, errorCorrectionLevel, mode)) {\n return currentVersion\n }\n }\n\n return undefined\n}\n\nfunction getReservedBitsCount (mode, version) {\n // Character count indicator + mode indicator bits\n return Mode.getCharCountIndicator(mode, version) + 4\n}\n\nfunction getTotalBitsFromDataArray (segments, version) {\n let totalBits = 0\n\n segments.forEach(function (data) {\n const reservedBits = getReservedBitsCount(data.mode, version)\n totalBits += reservedBits + data.getBitsLength()\n })\n\n return totalBits\n}\n\nfunction getBestVersionForMixedData (segments, errorCorrectionLevel) {\n for (let currentVersion = 1; currentVersion <= 40; currentVersion++) {\n const length = getTotalBitsFromDataArray(segments, currentVersion)\n if (length <= exports.getCapacity(currentVersion, errorCorrectionLevel, Mode.MIXED)) {\n return currentVersion\n }\n }\n\n return undefined\n}\n\n/**\n * Returns version number from a value.\n * If value is not a valid version, returns defaultValue\n *\n * @param {Number|String} value QR Code version\n * @param {Number} defaultValue Fallback value\n * @return {Number} QR Code version number\n */\nexports.from = function from (value, defaultValue) {\n if (VersionCheck.isValid(value)) {\n return parseInt(value, 10)\n }\n\n return defaultValue\n}\n\n/**\n * Returns how much data can be stored with the specified QR code version\n * and error correction level\n *\n * @param {Number} version QR Code version (1-40)\n * @param {Number} errorCorrectionLevel Error correction level\n * @param {Mode} mode Data mode\n * @return {Number} Quantity of storable data\n */\nexports.getCapacity = function getCapacity (version, errorCorrectionLevel, mode) {\n if (!VersionCheck.isValid(version)) {\n throw new Error('Invalid QR Code version')\n }\n\n // Use Byte mode as default\n if (typeof mode === 'undefined') mode = Mode.BYTE\n\n // Total codewords for this QR code version (Data + Error correction)\n const totalCodewords = Utils.getSymbolTotalCodewords(version)\n\n // Total number of error correction codewords\n const ecTotalCodewords = ECCode.getTotalCodewordsCount(version, errorCorrectionLevel)\n\n // Total number of data codewords\n const dataTotalCodewordsBits = (totalCodewords - ecTotalCodewords) * 8\n\n if (mode === Mode.MIXED) return dataTotalCodewordsBits\n\n const usableBits = dataTotalCodewordsBits - getReservedBitsCount(mode, version)\n\n // Return max number of storable codewords\n switch (mode) {\n case Mode.NUMERIC:\n return Math.floor((usableBits / 10) * 3)\n\n case Mode.ALPHANUMERIC:\n return Math.floor((usableBits / 11) * 2)\n\n case Mode.KANJI:\n return Math.floor(usableBits / 13)\n\n case Mode.BYTE:\n default:\n return Math.floor(usableBits / 8)\n }\n}\n\n/**\n * Returns the minimum version needed to contain the amount of data\n *\n * @param {Segment} data Segment of data\n * @param {Number} [errorCorrectionLevel=H] Error correction level\n * @param {Mode} mode Data mode\n * @return {Number} QR Code version\n */\nexports.getBestVersionForData = function getBestVersionForData (data, errorCorrectionLevel) {\n let seg\n\n const ecl = ECLevel.from(errorCorrectionLevel, ECLevel.M)\n\n if (Array.isArray(data)) {\n if (data.length > 1) {\n return getBestVersionForMixedData(data, ecl)\n }\n\n if (data.length === 0) {\n return 1\n }\n\n seg = data[0]\n } else {\n seg = data\n }\n\n return getBestVersionForDataLength(seg.mode, seg.getLength(), ecl)\n}\n\n/**\n * Returns version information with relative error correction bits\n *\n * The version information is included in QR Code symbols of version 7 or larger.\n * It consists of an 18-bit sequence containing 6 data bits,\n * with 12 error correction bits calculated using the (18, 6) Golay code.\n *\n * @param {Number} version QR Code version\n * @return {Number} Encoded version info bits\n */\nexports.getEncodedBits = function getEncodedBits (version) {\n if (!VersionCheck.isValid(version) || version < 7) {\n throw new Error('Invalid QR Code version')\n }\n\n let d = version << 12\n\n while (Utils.getBCHDigit(d) - G18_BCH >= 0) {\n d ^= (G18 << (Utils.getBCHDigit(d) - G18_BCH))\n }\n\n return (version << 12) | d\n}\n","const Utils = require('./utils')\n\nconst G15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0)\nconst G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1)\nconst G15_BCH = Utils.getBCHDigit(G15)\n\n/**\n * Returns format information with relative error correction bits\n *\n * The format information is a 15-bit sequence containing 5 data bits,\n * with 10 error correction bits calculated using the (15, 5) BCH code.\n *\n * @param {Number} errorCorrectionLevel Error correction level\n * @param {Number} mask Mask pattern\n * @return {Number} Encoded format information bits\n */\nexports.getEncodedBits = function getEncodedBits (errorCorrectionLevel, mask) {\n const data = ((errorCorrectionLevel.bit << 3) | mask)\n let d = data << 10\n\n while (Utils.getBCHDigit(d) - G15_BCH >= 0) {\n d ^= (G15 << (Utils.getBCHDigit(d) - G15_BCH))\n }\n\n // xor final data with mask pattern in order to ensure that\n // no combination of Error Correction Level and data mask pattern\n // will result in an all-zero data string\n return ((data << 10) | d) ^ G15_MASK\n}\n","const Mode = require('./mode')\n\nfunction NumericData (data) {\n this.mode = Mode.NUMERIC\n this.data = data.toString()\n}\n\nNumericData.getBitsLength = function getBitsLength (length) {\n return 10 * Math.floor(length / 3) + ((length % 3) ? ((length % 3) * 3 + 1) : 0)\n}\n\nNumericData.prototype.getLength = function getLength () {\n return this.data.length\n}\n\nNumericData.prototype.getBitsLength = function getBitsLength () {\n return NumericData.getBitsLength(this.data.length)\n}\n\nNumericData.prototype.write = function write (bitBuffer) {\n let i, group, value\n\n // The input data string is divided into groups of three digits,\n // and each group is converted to its 10-bit binary equivalent.\n for (i = 0; i + 3 <= this.data.length; i += 3) {\n group = this.data.substr(i, 3)\n value = parseInt(group, 10)\n\n bitBuffer.put(value, 10)\n }\n\n // If the number of input digits is not an exact multiple of three,\n // the final one or two digits are converted to 4 or 7 bits respectively.\n const remainingNum = this.data.length - i\n if (remainingNum > 0) {\n group = this.data.substr(i)\n value = parseInt(group, 10)\n\n bitBuffer.put(value, remainingNum * 3 + 1)\n }\n}\n\nmodule.exports = NumericData\n","const Mode = require('./mode')\n\n/**\n * Array of characters available in alphanumeric mode\n *\n * As per QR Code specification, to each character\n * is assigned a value from 0 to 44 which in this case coincides\n * with the array index\n *\n * @type {Array}\n */\nconst ALPHA_NUM_CHARS = [\n '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',\n 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',\n 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',\n ' ', '$', '%', '*', '+', '-', '.', '/', ':'\n]\n\nfunction AlphanumericData (data) {\n this.mode = Mode.ALPHANUMERIC\n this.data = data\n}\n\nAlphanumericData.getBitsLength = function getBitsLength (length) {\n return 11 * Math.floor(length / 2) + 6 * (length % 2)\n}\n\nAlphanumericData.prototype.getLength = function getLength () {\n return this.data.length\n}\n\nAlphanumericData.prototype.getBitsLength = function getBitsLength () {\n return AlphanumericData.getBitsLength(this.data.length)\n}\n\nAlphanumericData.prototype.write = function write (bitBuffer) {\n let i\n\n // Input data characters are divided into groups of two characters\n // and encoded as 11-bit binary codes.\n for (i = 0; i + 2 <= this.data.length; i += 2) {\n // The character value of the first character is multiplied by 45\n let value = ALPHA_NUM_CHARS.indexOf(this.data[i]) * 45\n\n // The character value of the second digit is added to the product\n value += ALPHA_NUM_CHARS.indexOf(this.data[i + 1])\n\n // The sum is then stored as 11-bit binary number\n bitBuffer.put(value, 11)\n }\n\n // If the number of input data characters is not a multiple of two,\n // the character value of the final character is encoded as a 6-bit binary number.\n if (this.data.length % 2) {\n bitBuffer.put(ALPHA_NUM_CHARS.indexOf(this.data[i]), 6)\n }\n}\n\nmodule.exports = AlphanumericData\n","const encodeUtf8 = require('encode-utf8')\nconst Mode = require('./mode')\n\nfunction ByteData (data) {\n this.mode = Mode.BYTE\n if (typeof (data) === 'string') {\n data = encodeUtf8(data)\n }\n this.data = new Uint8Array(data)\n}\n\nByteData.getBitsLength = function getBitsLength (length) {\n return length * 8\n}\n\nByteData.prototype.getLength = function getLength () {\n return this.data.length\n}\n\nByteData.prototype.getBitsLength = function getBitsLength () {\n return ByteData.getBitsLength(this.data.length)\n}\n\nByteData.prototype.write = function (bitBuffer) {\n for (let i = 0, l = this.data.length; i < l; i++) {\n bitBuffer.put(this.data[i], 8)\n }\n}\n\nmodule.exports = ByteData\n","'use strict'\n\nmodule.exports = function encodeUtf8 (input) {\n var result = []\n var size = input.length\n\n for (var index = 0; index < size; index++) {\n var point = input.charCodeAt(index)\n\n if (point >= 0xD800 && point <= 0xDBFF && size > index + 1) {\n var second = input.charCodeAt(index + 1)\n\n if (second >= 0xDC00 && second <= 0xDFFF) {\n // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae\n point = (point - 0xD800) * 0x400 + second - 0xDC00 + 0x10000\n index += 1\n }\n }\n\n // US-ASCII\n if (point < 0x80) {\n result.push(point)\n continue\n }\n\n // 2-byte UTF-8\n if (point < 0x800) {\n result.push((point >> 6) | 192)\n result.push((point & 63) | 128)\n continue\n }\n\n // 3-byte UTF-8\n if (point < 0xD800 || (point >= 0xE000 && point < 0x10000)) {\n result.push((point >> 12) | 224)\n result.push(((point >> 6) & 63) | 128)\n result.push((point & 63) | 128)\n continue\n }\n\n // 4-byte UTF-8\n if (point >= 0x10000 && point <= 0x10FFFF) {\n result.push((point >> 18) | 240)\n result.push(((point >> 12) & 63) | 128)\n result.push(((point >> 6) & 63) | 128)\n result.push((point & 63) | 128)\n continue\n }\n\n // Invalid character\n result.push(0xEF, 0xBF, 0xBD)\n }\n\n return new Uint8Array(result).buffer\n}\n","const Mode = require('./mode')\nconst Utils = require('./utils')\n\nfunction KanjiData (data) {\n this.mode = Mode.KANJI\n this.data = data\n}\n\nKanjiData.getBitsLength = function getBitsLength (length) {\n return length * 13\n}\n\nKanjiData.prototype.getLength = function getLength () {\n return this.data.length\n}\n\nKanjiData.prototype.getBitsLength = function getBitsLength () {\n return KanjiData.getBitsLength(this.data.length)\n}\n\nKanjiData.prototype.write = function (bitBuffer) {\n let i\n\n // In the Shift JIS system, Kanji characters are represented by a two byte combination.\n // These byte values are shifted from the JIS X 0208 values.\n // JIS X 0208 gives details of the shift coded representation.\n for (i = 0; i < this.data.length; i++) {\n let value = Utils.toSJIS(this.data[i])\n\n // For characters with Shift JIS values from 0x8140 to 0x9FFC:\n if (value >= 0x8140 && value <= 0x9FFC) {\n // Subtract 0x8140 from Shift JIS value\n value -= 0x8140\n\n // For characters with Shift JIS values from 0xE040 to 0xEBBF\n } else if (value >= 0xE040 && value <= 0xEBBF) {\n // Subtract 0xC140 from Shift JIS value\n value -= 0xC140\n } else {\n throw new Error(\n 'Invalid SJIS character: ' + this.data[i] + '\\n' +\n 'Make sure your charset is UTF-8')\n }\n\n // Multiply most significant byte of result by 0xC0\n // and add least significant byte to product\n value = (((value >>> 8) & 0xff) * 0xC0) + (value & 0xff)\n\n // Convert result to a 13-bit binary string\n bitBuffer.put(value, 13)\n }\n}\n\nmodule.exports = KanjiData\n","'use strict';\n\n/******************************************************************************\n * Created 2008-08-19.\n *\n * Dijkstra path-finding functions. Adapted from the Dijkstar Python project.\n *\n * Copyright (C) 2008\n * Wyatt Baldwin \n * All rights reserved\n *\n * Licensed under the MIT license.\n *\n * http://www.opensource.org/licenses/mit-license.php\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *****************************************************************************/\nvar dijkstra = {\n single_source_shortest_paths: function(graph, s, d) {\n // Predecessor map for each node that has been encountered.\n // node ID => predecessor node ID\n var predecessors = {};\n\n // Costs of shortest paths from s to all nodes encountered.\n // node ID => cost\n var costs = {};\n costs[s] = 0;\n\n // Costs of shortest paths from s to all nodes encountered; differs from\n // `costs` in that it provides easy access to the node that currently has\n // the known shortest path from s.\n // XXX: Do we actually need both `costs` and `open`?\n var open = dijkstra.PriorityQueue.make();\n open.push(s, 0);\n\n var closest,\n u, v,\n cost_of_s_to_u,\n adjacent_nodes,\n cost_of_e,\n cost_of_s_to_u_plus_cost_of_e,\n cost_of_s_to_v,\n first_visit;\n while (!open.empty()) {\n // In the nodes remaining in graph that have a known cost from s,\n // find the node, u, that currently has the shortest path from s.\n closest = open.pop();\n u = closest.value;\n cost_of_s_to_u = closest.cost;\n\n // Get nodes adjacent to u...\n adjacent_nodes = graph[u] || {};\n\n // ...and explore the edges that connect u to those nodes, updating\n // the cost of the shortest paths to any or all of those nodes as\n // necessary. v is the node across the current edge from u.\n for (v in adjacent_nodes) {\n if (adjacent_nodes.hasOwnProperty(v)) {\n // Get the cost of the edge running from u to v.\n cost_of_e = adjacent_nodes[v];\n\n // Cost of s to u plus the cost of u to v across e--this is *a*\n // cost from s to v that may or may not be less than the current\n // known cost to v.\n cost_of_s_to_u_plus_cost_of_e = cost_of_s_to_u + cost_of_e;\n\n // If we haven't visited v yet OR if the current known cost from s to\n // v is greater than the new cost we just found (cost of s to u plus\n // cost of u to v across e), update v's cost in the cost list and\n // update v's predecessor in the predecessor list (it's now u).\n cost_of_s_to_v = costs[v];\n first_visit = (typeof costs[v] === 'undefined');\n if (first_visit || cost_of_s_to_v > cost_of_s_to_u_plus_cost_of_e) {\n costs[v] = cost_of_s_to_u_plus_cost_of_e;\n open.push(v, cost_of_s_to_u_plus_cost_of_e);\n predecessors[v] = u;\n }\n }\n }\n }\n\n if (typeof d !== 'undefined' && typeof costs[d] === 'undefined') {\n var msg = ['Could not find a path from ', s, ' to ', d, '.'].join('');\n throw new Error(msg);\n }\n\n return predecessors;\n },\n\n extract_shortest_path_from_predecessor_list: function(predecessors, d) {\n var nodes = [];\n var u = d;\n var predecessor;\n while (u) {\n nodes.push(u);\n predecessor = predecessors[u];\n u = predecessors[u];\n }\n nodes.reverse();\n return nodes;\n },\n\n find_path: function(graph, s, d) {\n var predecessors = dijkstra.single_source_shortest_paths(graph, s, d);\n return dijkstra.extract_shortest_path_from_predecessor_list(\n predecessors, d);\n },\n\n /**\n * A very naive priority queue implementation.\n */\n PriorityQueue: {\n make: function (opts) {\n var T = dijkstra.PriorityQueue,\n t = {},\n key;\n opts = opts || {};\n for (key in T) {\n if (T.hasOwnProperty(key)) {\n t[key] = T[key];\n }\n }\n t.queue = [];\n t.sorter = opts.sorter || T.default_sorter;\n return t;\n },\n\n default_sorter: function (a, b) {\n return a.cost - b.cost;\n },\n\n /**\n * Add a new item to the queue and ensure the highest priority element\n * is at the front of the queue.\n */\n push: function (value, cost) {\n var item = {value: value, cost: cost};\n this.queue.push(item);\n this.queue.sort(this.sorter);\n },\n\n /**\n * Return the highest priority element in the queue.\n */\n pop: function () {\n return this.queue.shift();\n },\n\n empty: function () {\n return this.queue.length === 0;\n }\n }\n};\n\n\n// node.js module exports\nif (typeof module !== 'undefined') {\n module.exports = dijkstra;\n}\n","const Mode = require('./mode')\nconst NumericData = require('./numeric-data')\nconst AlphanumericData = require('./alphanumeric-data')\nconst ByteData = require('./byte-data')\nconst KanjiData = require('./kanji-data')\nconst Regex = require('./regex')\nconst Utils = require('./utils')\nconst dijkstra = require('dijkstrajs')\n\n/**\n * Returns UTF8 byte length\n *\n * @param {String} str Input string\n * @return {Number} Number of byte\n */\nfunction getStringByteLength (str) {\n return unescape(encodeURIComponent(str)).length\n}\n\n/**\n * Get a list of segments of the specified mode\n * from a string\n *\n * @param {Mode} mode Segment mode\n * @param {String} str String to process\n * @return {Array} Array of object with segments data\n */\nfunction getSegments (regex, mode, str) {\n const segments = []\n let result\n\n while ((result = regex.exec(str)) !== null) {\n segments.push({\n data: result[0],\n index: result.index,\n mode: mode,\n length: result[0].length\n })\n }\n\n return segments\n}\n\n/**\n * Extracts a series of segments with the appropriate\n * modes from a string\n *\n * @param {String} dataStr Input string\n * @return {Array} Array of object with segments data\n */\nfunction getSegmentsFromString (dataStr) {\n const numSegs = getSegments(Regex.NUMERIC, Mode.NUMERIC, dataStr)\n const alphaNumSegs = getSegments(Regex.ALPHANUMERIC, Mode.ALPHANUMERIC, dataStr)\n let byteSegs\n let kanjiSegs\n\n if (Utils.isKanjiModeEnabled()) {\n byteSegs = getSegments(Regex.BYTE, Mode.BYTE, dataStr)\n kanjiSegs = getSegments(Regex.KANJI, Mode.KANJI, dataStr)\n } else {\n byteSegs = getSegments(Regex.BYTE_KANJI, Mode.BYTE, dataStr)\n kanjiSegs = []\n }\n\n const segs = numSegs.concat(alphaNumSegs, byteSegs, kanjiSegs)\n\n return segs\n .sort(function (s1, s2) {\n return s1.index - s2.index\n })\n .map(function (obj) {\n return {\n data: obj.data,\n mode: obj.mode,\n length: obj.length\n }\n })\n}\n\n/**\n * Returns how many bits are needed to encode a string of\n * specified length with the specified mode\n *\n * @param {Number} length String length\n * @param {Mode} mode Segment mode\n * @return {Number} Bit length\n */\nfunction getSegmentBitsLength (length, mode) {\n switch (mode) {\n case Mode.NUMERIC:\n return NumericData.getBitsLength(length)\n case Mode.ALPHANUMERIC:\n return AlphanumericData.getBitsLength(length)\n case Mode.KANJI:\n return KanjiData.getBitsLength(length)\n case Mode.BYTE:\n return ByteData.getBitsLength(length)\n }\n}\n\n/**\n * Merges adjacent segments which have the same mode\n *\n * @param {Array} segs Array of object with segments data\n * @return {Array} Array of object with segments data\n */\nfunction mergeSegments (segs) {\n return segs.reduce(function (acc, curr) {\n const prevSeg = acc.length - 1 >= 0 ? acc[acc.length - 1] : null\n if (prevSeg && prevSeg.mode === curr.mode) {\n acc[acc.length - 1].data += curr.data\n return acc\n }\n\n acc.push(curr)\n return acc\n }, [])\n}\n\n/**\n * Generates a list of all possible nodes combination which\n * will be used to build a segments graph.\n *\n * Nodes are divided by groups. Each group will contain a list of all the modes\n * in which is possible to encode the given text.\n *\n * For example the text '12345' can be encoded as Numeric, Alphanumeric or Byte.\n * The group for '12345' will contain then 3 objects, one for each\n * possible encoding mode.\n *\n * Each node represents a possible segment.\n *\n * @param {Array} segs Array of object with segments data\n * @return {Array} Array of object with segments data\n */\nfunction buildNodes (segs) {\n const nodes = []\n for (let i = 0; i < segs.length; i++) {\n const seg = segs[i]\n\n switch (seg.mode) {\n case Mode.NUMERIC:\n nodes.push([seg,\n { data: seg.data, mode: Mode.ALPHANUMERIC, length: seg.length },\n { data: seg.data, mode: Mode.BYTE, length: seg.length }\n ])\n break\n case Mode.ALPHANUMERIC:\n nodes.push([seg,\n { data: seg.data, mode: Mode.BYTE, length: seg.length }\n ])\n break\n case Mode.KANJI:\n nodes.push([seg,\n { data: seg.data, mode: Mode.BYTE, length: getStringByteLength(seg.data) }\n ])\n break\n case Mode.BYTE:\n nodes.push([\n { data: seg.data, mode: Mode.BYTE, length: getStringByteLength(seg.data) }\n ])\n }\n }\n\n return nodes\n}\n\n/**\n * Builds a graph from a list of nodes.\n * All segments in each node group will be connected with all the segments of\n * the next group and so on.\n *\n * At each connection will be assigned a weight depending on the\n * segment's byte length.\n *\n * @param {Array} nodes Array of object with segments data\n * @param {Number} version QR Code version\n * @return {Object} Graph of all possible segments\n */\nfunction buildGraph (nodes, version) {\n const table = {}\n const graph = { start: {} }\n let prevNodeIds = ['start']\n\n for (let i = 0; i < nodes.length; i++) {\n const nodeGroup = nodes[i]\n const currentNodeIds = []\n\n for (let j = 0; j < nodeGroup.length; j++) {\n const node = nodeGroup[j]\n const key = '' + i + j\n\n currentNodeIds.push(key)\n table[key] = { node: node, lastCount: 0 }\n graph[key] = {}\n\n for (let n = 0; n < prevNodeIds.length; n++) {\n const prevNodeId = prevNodeIds[n]\n\n if (table[prevNodeId] && table[prevNodeId].node.mode === node.mode) {\n graph[prevNodeId][key] =\n getSegmentBitsLength(table[prevNodeId].lastCount + node.length, node.mode) -\n getSegmentBitsLength(table[prevNodeId].lastCount, node.mode)\n\n table[prevNodeId].lastCount += node.length\n } else {\n if (table[prevNodeId]) table[prevNodeId].lastCount = node.length\n\n graph[prevNodeId][key] = getSegmentBitsLength(node.length, node.mode) +\n 4 + Mode.getCharCountIndicator(node.mode, version) // switch cost\n }\n }\n }\n\n prevNodeIds = currentNodeIds\n }\n\n for (let n = 0; n < prevNodeIds.length; n++) {\n graph[prevNodeIds[n]].end = 0\n }\n\n return { map: graph, table: table }\n}\n\n/**\n * Builds a segment from a specified data and mode.\n * If a mode is not specified, the more suitable will be used.\n *\n * @param {String} data Input data\n * @param {Mode | String} modesHint Data mode\n * @return {Segment} Segment\n */\nfunction buildSingleSegment (data, modesHint) {\n let mode\n const bestMode = Mode.getBestModeForData(data)\n\n mode = Mode.from(modesHint, bestMode)\n\n // Make sure data can be encoded\n if (mode !== Mode.BYTE && mode.bit < bestMode.bit) {\n throw new Error('\"' + data + '\"' +\n ' cannot be encoded with mode ' + Mode.toString(mode) +\n '.\\n Suggested mode is: ' + Mode.toString(bestMode))\n }\n\n // Use Mode.BYTE if Kanji support is disabled\n if (mode === Mode.KANJI && !Utils.isKanjiModeEnabled()) {\n mode = Mode.BYTE\n }\n\n switch (mode) {\n case Mode.NUMERIC:\n return new NumericData(data)\n\n case Mode.ALPHANUMERIC:\n return new AlphanumericData(data)\n\n case Mode.KANJI:\n return new KanjiData(data)\n\n case Mode.BYTE:\n return new ByteData(data)\n }\n}\n\n/**\n * Builds a list of segments from an array.\n * Array can contain Strings or Objects with segment's info.\n *\n * For each item which is a string, will be generated a segment with the given\n * string and the more appropriate encoding mode.\n *\n * For each item which is an object, will be generated a segment with the given\n * data and mode.\n * Objects must contain at least the property \"data\".\n * If property \"mode\" is not present, the more suitable mode will be used.\n *\n * @param {Array} array Array of objects with segments data\n * @return {Array} Array of Segments\n */\nexports.fromArray = function fromArray (array) {\n return array.reduce(function (acc, seg) {\n if (typeof seg === 'string') {\n acc.push(buildSingleSegment(seg, null))\n } else if (seg.data) {\n acc.push(buildSingleSegment(seg.data, seg.mode))\n }\n\n return acc\n }, [])\n}\n\n/**\n * Builds an optimized sequence of segments from a string,\n * which will produce the shortest possible bitstream.\n *\n * @param {String} data Input string\n * @param {Number} version QR Code version\n * @return {Array} Array of segments\n */\nexports.fromString = function fromString (data, version) {\n const segs = getSegmentsFromString(data, Utils.isKanjiModeEnabled())\n\n const nodes = buildNodes(segs)\n const graph = buildGraph(nodes, version)\n const path = dijkstra.find_path(graph.map, 'start', 'end')\n\n const optimizedSegs = []\n for (let i = 1; i < path.length - 1; i++) {\n optimizedSegs.push(graph.table[path[i]].node)\n }\n\n return exports.fromArray(mergeSegments(optimizedSegs))\n}\n\n/**\n * Splits a string in various segments with the modes which\n * best represent their content.\n * The produced segments are far from being optimized.\n * The output of this function is only used to estimate a QR Code version\n * which may contain the data.\n *\n * @param {string} data Input string\n * @return {Array} Array of segments\n */\nexports.rawSplit = function rawSplit (data) {\n return exports.fromArray(\n getSegmentsFromString(data, Utils.isKanjiModeEnabled())\n )\n}\n","const Utils = require('./utils')\nconst ECLevel = require('./error-correction-level')\nconst BitBuffer = require('./bit-buffer')\nconst BitMatrix = require('./bit-matrix')\nconst AlignmentPattern = require('./alignment-pattern')\nconst FinderPattern = require('./finder-pattern')\nconst MaskPattern = require('./mask-pattern')\nconst ECCode = require('./error-correction-code')\nconst ReedSolomonEncoder = require('./reed-solomon-encoder')\nconst Version = require('./version')\nconst FormatInfo = require('./format-info')\nconst Mode = require('./mode')\nconst Segments = require('./segments')\n\n/**\n * QRCode for JavaScript\n *\n * modified by Ryan Day for nodejs support\n * Copyright (c) 2011 Ryan Day\n *\n * Licensed under the MIT license:\n * http://www.opensource.org/licenses/mit-license.php\n *\n//---------------------------------------------------------------------\n// QRCode for JavaScript\n//\n// Copyright (c) 2009 Kazuhiko Arase\n//\n// URL: http://www.d-project.com/\n//\n// Licensed under the MIT license:\n// http://www.opensource.org/licenses/mit-license.php\n//\n// The word \"QR Code\" is registered trademark of\n// DENSO WAVE INCORPORATED\n// http://www.denso-wave.com/qrcode/faqpatent-e.html\n//\n//---------------------------------------------------------------------\n*/\n\n/**\n * Add finder patterns bits to matrix\n *\n * @param {BitMatrix} matrix Modules matrix\n * @param {Number} version QR Code version\n */\nfunction setupFinderPattern (matrix, version) {\n const size = matrix.size\n const pos = FinderPattern.getPositions(version)\n\n for (let i = 0; i < pos.length; i++) {\n const row = pos[i][0]\n const col = pos[i][1]\n\n for (let r = -1; r <= 7; r++) {\n if (row + r <= -1 || size <= row + r) continue\n\n for (let c = -1; c <= 7; c++) {\n if (col + c <= -1 || size <= col + c) continue\n\n if ((r >= 0 && r <= 6 && (c === 0 || c === 6)) ||\n (c >= 0 && c <= 6 && (r === 0 || r === 6)) ||\n (r >= 2 && r <= 4 && c >= 2 && c <= 4)) {\n matrix.set(row + r, col + c, true, true)\n } else {\n matrix.set(row + r, col + c, false, true)\n }\n }\n }\n }\n}\n\n/**\n * Add timing pattern bits to matrix\n *\n * Note: this function must be called before {@link setupAlignmentPattern}\n *\n * @param {BitMatrix} matrix Modules matrix\n */\nfunction setupTimingPattern (matrix) {\n const size = matrix.size\n\n for (let r = 8; r < size - 8; r++) {\n const value = r % 2 === 0\n matrix.set(r, 6, value, true)\n matrix.set(6, r, value, true)\n }\n}\n\n/**\n * Add alignment patterns bits to matrix\n *\n * Note: this function must be called after {@link setupTimingPattern}\n *\n * @param {BitMatrix} matrix Modules matrix\n * @param {Number} version QR Code version\n */\nfunction setupAlignmentPattern (matrix, version) {\n const pos = AlignmentPattern.getPositions(version)\n\n for (let i = 0; i < pos.length; i++) {\n const row = pos[i][0]\n const col = pos[i][1]\n\n for (let r = -2; r <= 2; r++) {\n for (let c = -2; c <= 2; c++) {\n if (r === -2 || r === 2 || c === -2 || c === 2 ||\n (r === 0 && c === 0)) {\n matrix.set(row + r, col + c, true, true)\n } else {\n matrix.set(row + r, col + c, false, true)\n }\n }\n }\n }\n}\n\n/**\n * Add version info bits to matrix\n *\n * @param {BitMatrix} matrix Modules matrix\n * @param {Number} version QR Code version\n */\nfunction setupVersionInfo (matrix, version) {\n const size = matrix.size\n const bits = Version.getEncodedBits(version)\n let row, col, mod\n\n for (let i = 0; i < 18; i++) {\n row = Math.floor(i / 3)\n col = i % 3 + size - 8 - 3\n mod = ((bits >> i) & 1) === 1\n\n matrix.set(row, col, mod, true)\n matrix.set(col, row, mod, true)\n }\n}\n\n/**\n * Add format info bits to matrix\n *\n * @param {BitMatrix} matrix Modules matrix\n * @param {ErrorCorrectionLevel} errorCorrectionLevel Error correction level\n * @param {Number} maskPattern Mask pattern reference value\n */\nfunction setupFormatInfo (matrix, errorCorrectionLevel, maskPattern) {\n const size = matrix.size\n const bits = FormatInfo.getEncodedBits(errorCorrectionLevel, maskPattern)\n let i, mod\n\n for (i = 0; i < 15; i++) {\n mod = ((bits >> i) & 1) === 1\n\n // vertical\n if (i < 6) {\n matrix.set(i, 8, mod, true)\n } else if (i < 8) {\n matrix.set(i + 1, 8, mod, true)\n } else {\n matrix.set(size - 15 + i, 8, mod, true)\n }\n\n // horizontal\n if (i < 8) {\n matrix.set(8, size - i - 1, mod, true)\n } else if (i < 9) {\n matrix.set(8, 15 - i - 1 + 1, mod, true)\n } else {\n matrix.set(8, 15 - i - 1, mod, true)\n }\n }\n\n // fixed module\n matrix.set(size - 8, 8, 1, true)\n}\n\n/**\n * Add encoded data bits to matrix\n *\n * @param {BitMatrix} matrix Modules matrix\n * @param {Uint8Array} data Data codewords\n */\nfunction setupData (matrix, data) {\n const size = matrix.size\n let inc = -1\n let row = size - 1\n let bitIndex = 7\n let byteIndex = 0\n\n for (let col = size - 1; col > 0; col -= 2) {\n if (col === 6) col--\n\n while (true) {\n for (let c = 0; c < 2; c++) {\n if (!matrix.isReserved(row, col - c)) {\n let dark = false\n\n if (byteIndex < data.length) {\n dark = (((data[byteIndex] >>> bitIndex) & 1) === 1)\n }\n\n matrix.set(row, col - c, dark)\n bitIndex--\n\n if (bitIndex === -1) {\n byteIndex++\n bitIndex = 7\n }\n }\n }\n\n row += inc\n\n if (row < 0 || size <= row) {\n row -= inc\n inc = -inc\n break\n }\n }\n }\n}\n\n/**\n * Create encoded codewords from data input\n *\n * @param {Number} version QR Code version\n * @param {ErrorCorrectionLevel} errorCorrectionLevel Error correction level\n * @param {ByteData} data Data input\n * @return {Uint8Array} Buffer containing encoded codewords\n */\nfunction createData (version, errorCorrectionLevel, segments) {\n // Prepare data buffer\n const buffer = new BitBuffer()\n\n segments.forEach(function (data) {\n // prefix data with mode indicator (4 bits)\n buffer.put(data.mode.bit, 4)\n\n // Prefix data with character count indicator.\n // The character count indicator is a string of bits that represents the\n // number of characters that are being encoded.\n // The character count indicator must be placed after the mode indicator\n // and must be a certain number of bits long, depending on the QR version\n // and data mode\n // @see {@link Mode.getCharCountIndicator}.\n buffer.put(data.getLength(), Mode.getCharCountIndicator(data.mode, version))\n\n // add binary data sequence to buffer\n data.write(buffer)\n })\n\n // Calculate required number of bits\n const totalCodewords = Utils.getSymbolTotalCodewords(version)\n const ecTotalCodewords = ECCode.getTotalCodewordsCount(version, errorCorrectionLevel)\n const dataTotalCodewordsBits = (totalCodewords - ecTotalCodewords) * 8\n\n // Add a terminator.\n // If the bit string is shorter than the total number of required bits,\n // a terminator of up to four 0s must be added to the right side of the string.\n // If the bit string is more than four bits shorter than the required number of bits,\n // add four 0s to the end.\n if (buffer.getLengthInBits() + 4 <= dataTotalCodewordsBits) {\n buffer.put(0, 4)\n }\n\n // If the bit string is fewer than four bits shorter, add only the number of 0s that\n // are needed to reach the required number of bits.\n\n // After adding the terminator, if the number of bits in the string is not a multiple of 8,\n // pad the string on the right with 0s to make the string's length a multiple of 8.\n while (buffer.getLengthInBits() % 8 !== 0) {\n buffer.putBit(0)\n }\n\n // Add pad bytes if the string is still shorter than the total number of required bits.\n // Extend the buffer to fill the data capacity of the symbol corresponding to\n // the Version and Error Correction Level by adding the Pad Codewords 11101100 (0xEC)\n // and 00010001 (0x11) alternately.\n const remainingByte = (dataTotalCodewordsBits - buffer.getLengthInBits()) / 8\n for (let i = 0; i < remainingByte; i++) {\n buffer.put(i % 2 ? 0x11 : 0xEC, 8)\n }\n\n return createCodewords(buffer, version, errorCorrectionLevel)\n}\n\n/**\n * Encode input data with Reed-Solomon and return codewords with\n * relative error correction bits\n *\n * @param {BitBuffer} bitBuffer Data to encode\n * @param {Number} version QR Code version\n * @param {ErrorCorrectionLevel} errorCorrectionLevel Error correction level\n * @return {Uint8Array} Buffer containing encoded codewords\n */\nfunction createCodewords (bitBuffer, version, errorCorrectionLevel) {\n // Total codewords for this QR code version (Data + Error correction)\n const totalCodewords = Utils.getSymbolTotalCodewords(version)\n\n // Total number of error correction codewords\n const ecTotalCodewords = ECCode.getTotalCodewordsCount(version, errorCorrectionLevel)\n\n // Total number of data codewords\n const dataTotalCodewords = totalCodewords - ecTotalCodewords\n\n // Total number of blocks\n const ecTotalBlocks = ECCode.getBlocksCount(version, errorCorrectionLevel)\n\n // Calculate how many blocks each group should contain\n const blocksInGroup2 = totalCodewords % ecTotalBlocks\n const blocksInGroup1 = ecTotalBlocks - blocksInGroup2\n\n const totalCodewordsInGroup1 = Math.floor(totalCodewords / ecTotalBlocks)\n\n const dataCodewordsInGroup1 = Math.floor(dataTotalCodewords / ecTotalBlocks)\n const dataCodewordsInGroup2 = dataCodewordsInGroup1 + 1\n\n // Number of EC codewords is the same for both groups\n const ecCount = totalCodewordsInGroup1 - dataCodewordsInGroup1\n\n // Initialize a Reed-Solomon encoder with a generator polynomial of degree ecCount\n const rs = new ReedSolomonEncoder(ecCount)\n\n let offset = 0\n const dcData = new Array(ecTotalBlocks)\n const ecData = new Array(ecTotalBlocks)\n let maxDataSize = 0\n const buffer = new Uint8Array(bitBuffer.buffer)\n\n // Divide the buffer into the required number of blocks\n for (let b = 0; b < ecTotalBlocks; b++) {\n const dataSize = b < blocksInGroup1 ? dataCodewordsInGroup1 : dataCodewordsInGroup2\n\n // extract a block of data from buffer\n dcData[b] = buffer.slice(offset, offset + dataSize)\n\n // Calculate EC codewords for this data block\n ecData[b] = rs.encode(dcData[b])\n\n offset += dataSize\n maxDataSize = Math.max(maxDataSize, dataSize)\n }\n\n // Create final data\n // Interleave the data and error correction codewords from each block\n const data = new Uint8Array(totalCodewords)\n let index = 0\n let i, r\n\n // Add data codewords\n for (i = 0; i < maxDataSize; i++) {\n for (r = 0; r < ecTotalBlocks; r++) {\n if (i < dcData[r].length) {\n data[index++] = dcData[r][i]\n }\n }\n }\n\n // Apped EC codewords\n for (i = 0; i < ecCount; i++) {\n for (r = 0; r < ecTotalBlocks; r++) {\n data[index++] = ecData[r][i]\n }\n }\n\n return data\n}\n\n/**\n * Build QR Code symbol\n *\n * @param {String} data Input string\n * @param {Number} version QR Code version\n * @param {ErrorCorretionLevel} errorCorrectionLevel Error level\n * @param {MaskPattern} maskPattern Mask pattern\n * @return {Object} Object containing symbol data\n */\nfunction createSymbol (data, version, errorCorrectionLevel, maskPattern) {\n let segments\n\n if (Array.isArray(data)) {\n segments = Segments.fromArray(data)\n } else if (typeof data === 'string') {\n let estimatedVersion = version\n\n if (!estimatedVersion) {\n const rawSegments = Segments.rawSplit(data)\n\n // Estimate best version that can contain raw splitted segments\n estimatedVersion = Version.getBestVersionForData(rawSegments, errorCorrectionLevel)\n }\n\n // Build optimized segments\n // If estimated version is undefined, try with the highest version\n segments = Segments.fromString(data, estimatedVersion || 40)\n } else {\n throw new Error('Invalid data')\n }\n\n // Get the min version that can contain data\n const bestVersion = Version.getBestVersionForData(segments, errorCorrectionLevel)\n\n // If no version is found, data cannot be stored\n if (!bestVersion) {\n throw new Error('The amount of data is too big to be stored in a QR Code')\n }\n\n // If not specified, use min version as default\n if (!version) {\n version = bestVersion\n\n // Check if the specified version can contain the data\n } else if (version < bestVersion) {\n throw new Error('\\n' +\n 'The chosen QR Code version cannot contain this amount of data.\\n' +\n 'Minimum version required to store current data is: ' + bestVersion + '.\\n'\n )\n }\n\n const dataBits = createData(version, errorCorrectionLevel, segments)\n\n // Allocate matrix buffer\n const moduleCount = Utils.getSymbolSize(version)\n const modules = new BitMatrix(moduleCount)\n\n // Add function modules\n setupFinderPattern(modules, version)\n setupTimingPattern(modules)\n setupAlignmentPattern(modules, version)\n\n // Add temporary dummy bits for format info just to set them as reserved.\n // This is needed to prevent these bits from being masked by {@link MaskPattern.applyMask}\n // since the masking operation must be performed only on the encoding region.\n // These blocks will be replaced with correct values later in code.\n setupFormatInfo(modules, errorCorrectionLevel, 0)\n\n if (version >= 7) {\n setupVersionInfo(modules, version)\n }\n\n // Add data codewords\n setupData(modules, dataBits)\n\n if (isNaN(maskPattern)) {\n // Find best mask pattern\n maskPattern = MaskPattern.getBestMask(modules,\n setupFormatInfo.bind(null, modules, errorCorrectionLevel))\n }\n\n // Apply mask pattern\n MaskPattern.applyMask(maskPattern, modules)\n\n // Replace format info bits with correct values\n setupFormatInfo(modules, errorCorrectionLevel, maskPattern)\n\n return {\n modules: modules,\n version: version,\n errorCorrectionLevel: errorCorrectionLevel,\n maskPattern: maskPattern,\n segments: segments\n }\n}\n\n/**\n * QR Code\n *\n * @param {String | Array} data Input data\n * @param {Object} options Optional configurations\n * @param {Number} options.version QR Code version\n * @param {String} options.errorCorrectionLevel Error correction level\n * @param {Function} options.toSJISFunc Helper func to convert utf8 to sjis\n */\nexports.create = function create (data, options) {\n if (typeof data === 'undefined' || data === '') {\n throw new Error('No input text')\n }\n\n let errorCorrectionLevel = ECLevel.M\n let version\n let mask\n\n if (typeof options !== 'undefined') {\n // Use higher error correction level as default\n errorCorrectionLevel = ECLevel.from(options.errorCorrectionLevel, ECLevel.M)\n version = Version.from(options.version)\n mask = MaskPattern.from(options.maskPattern)\n\n if (options.toSJISFunc) {\n Utils.setToSJISFunction(options.toSJISFunc)\n }\n }\n\n return createSymbol(data, version, errorCorrectionLevel, mask)\n}\n","function hex2rgba (hex) {\n if (typeof hex === 'number') {\n hex = hex.toString()\n }\n\n if (typeof hex !== 'string') {\n throw new Error('Color should be defined as hex string')\n }\n\n let hexCode = hex.slice().replace('#', '').split('')\n if (hexCode.length < 3 || hexCode.length === 5 || hexCode.length > 8) {\n throw new Error('Invalid hex color: ' + hex)\n }\n\n // Convert from short to long form (fff -> ffffff)\n if (hexCode.length === 3 || hexCode.length === 4) {\n hexCode = Array.prototype.concat.apply([], hexCode.map(function (c) {\n return [c, c]\n }))\n }\n\n // Add default alpha value\n if (hexCode.length === 6) hexCode.push('F', 'F')\n\n const hexValue = parseInt(hexCode.join(''), 16)\n\n return {\n r: (hexValue >> 24) & 255,\n g: (hexValue >> 16) & 255,\n b: (hexValue >> 8) & 255,\n a: hexValue & 255,\n hex: '#' + hexCode.slice(0, 6).join('')\n }\n}\n\nexports.getOptions = function getOptions (options) {\n if (!options) options = {}\n if (!options.color) options.color = {}\n\n const margin = typeof options.margin === 'undefined' ||\n options.margin === null ||\n options.margin < 0\n ? 4\n : options.margin\n\n const width = options.width && options.width >= 21 ? options.width : undefined\n const scale = options.scale || 4\n\n return {\n width: width,\n scale: width ? 4 : scale,\n margin: margin,\n color: {\n dark: hex2rgba(options.color.dark || '#000000ff'),\n light: hex2rgba(options.color.light || '#ffffffff')\n },\n type: options.type,\n rendererOpts: options.rendererOpts || {}\n }\n}\n\nexports.getScale = function getScale (qrSize, opts) {\n return opts.width && opts.width >= qrSize + opts.margin * 2\n ? opts.width / (qrSize + opts.margin * 2)\n : opts.scale\n}\n\nexports.getImageWidth = function getImageWidth (qrSize, opts) {\n const scale = exports.getScale(qrSize, opts)\n return Math.floor((qrSize + opts.margin * 2) * scale)\n}\n\nexports.qrToImageData = function qrToImageData (imgData, qr, opts) {\n const size = qr.modules.size\n const data = qr.modules.data\n const scale = exports.getScale(size, opts)\n const symbolSize = Math.floor((size + opts.margin * 2) * scale)\n const scaledMargin = opts.margin * scale\n const palette = [opts.color.light, opts.color.dark]\n\n for (let i = 0; i < symbolSize; i++) {\n for (let j = 0; j < symbolSize; j++) {\n let posDst = (i * symbolSize + j) * 4\n let pxColor = opts.color.light\n\n if (i >= scaledMargin && j >= scaledMargin &&\n i < symbolSize - scaledMargin && j < symbolSize - scaledMargin) {\n const iSrc = Math.floor((i - scaledMargin) / scale)\n const jSrc = Math.floor((j - scaledMargin) / scale)\n pxColor = palette[data[iSrc * size + jSrc] ? 1 : 0]\n }\n\n imgData[posDst++] = pxColor.r\n imgData[posDst++] = pxColor.g\n imgData[posDst++] = pxColor.b\n imgData[posDst] = pxColor.a\n }\n }\n}\n","const Utils = require('./utils')\n\nfunction clearCanvas (ctx, canvas, size) {\n ctx.clearRect(0, 0, canvas.width, canvas.height)\n\n if (!canvas.style) canvas.style = {}\n canvas.height = size\n canvas.width = size\n canvas.style.height = size + 'px'\n canvas.style.width = size + 'px'\n}\n\nfunction getCanvasElement () {\n try {\n return document.createElement('canvas')\n } catch (e) {\n throw new Error('You need to specify a canvas element')\n }\n}\n\nexports.render = function render (qrData, canvas, options) {\n let opts = options\n let canvasEl = canvas\n\n if (typeof opts === 'undefined' && (!canvas || !canvas.getContext)) {\n opts = canvas\n canvas = undefined\n }\n\n if (!canvas) {\n canvasEl = getCanvasElement()\n }\n\n opts = Utils.getOptions(opts)\n const size = Utils.getImageWidth(qrData.modules.size, opts)\n\n const ctx = canvasEl.getContext('2d')\n const image = ctx.createImageData(size, size)\n Utils.qrToImageData(image.data, qrData, opts)\n\n clearCanvas(ctx, canvasEl, size)\n ctx.putImageData(image, 0, 0)\n\n return canvasEl\n}\n\nexports.renderToDataURL = function renderToDataURL (qrData, canvas, options) {\n let opts = options\n\n if (typeof opts === 'undefined' && (!canvas || !canvas.getContext)) {\n opts = canvas\n canvas = undefined\n }\n\n if (!opts) opts = {}\n\n const canvasEl = exports.render(qrData, canvas, opts)\n\n const type = opts.type || 'image/png'\n const rendererOpts = opts.rendererOpts || {}\n\n return canvasEl.toDataURL(type, rendererOpts.quality)\n}\n","const Utils = require('./utils')\n\nfunction getColorAttrib (color, attrib) {\n const alpha = color.a / 255\n const str = attrib + '=\"' + color.hex + '\"'\n\n return alpha < 1\n ? str + ' ' + attrib + '-opacity=\"' + alpha.toFixed(2).slice(1) + '\"'\n : str\n}\n\nfunction svgCmd (cmd, x, y) {\n let str = cmd + x\n if (typeof y !== 'undefined') str += ' ' + y\n\n return str\n}\n\nfunction qrToPath (data, size, margin) {\n let path = ''\n let moveBy = 0\n let newRow = false\n let lineLength = 0\n\n for (let i = 0; i < data.length; i++) {\n const col = Math.floor(i % size)\n const row = Math.floor(i / size)\n\n if (!col && !newRow) newRow = true\n\n if (data[i]) {\n lineLength++\n\n if (!(i > 0 && col > 0 && data[i - 1])) {\n path += newRow\n ? svgCmd('M', col + margin, 0.5 + row + margin)\n : svgCmd('m', moveBy, 0)\n\n moveBy = 0\n newRow = false\n }\n\n if (!(col + 1 < size && data[i + 1])) {\n path += svgCmd('h', lineLength)\n lineLength = 0\n }\n } else {\n moveBy++\n }\n }\n\n return path\n}\n\nexports.render = function render (qrData, options, cb) {\n const opts = Utils.getOptions(options)\n const size = qrData.modules.size\n const data = qrData.modules.data\n const qrcodesize = size + opts.margin * 2\n\n const bg = !opts.color.light.a\n ? ''\n : ''\n\n const path =\n ''\n\n const viewBox = 'viewBox=\"' + '0 0 ' + qrcodesize + ' ' + qrcodesize + '\"'\n\n const width = !opts.width ? '' : 'width=\"' + opts.width + '\" height=\"' + opts.width + '\" '\n\n const svgTag = '' + bg + path + '\\n'\n\n if (typeof cb === 'function') {\n cb(null, svgTag)\n }\n\n return svgTag\n}\n","\nconst canPromise = require('./can-promise')\n\nconst QRCode = require('./core/qrcode')\nconst CanvasRenderer = require('./renderer/canvas')\nconst SvgRenderer = require('./renderer/svg-tag.js')\n\nfunction renderCanvas (renderFunc, canvas, text, opts, cb) {\n const args = [].slice.call(arguments, 1)\n const argsNum = args.length\n const isLastArgCb = typeof args[argsNum - 1] === 'function'\n\n if (!isLastArgCb && !canPromise()) {\n throw new Error('Callback required as last argument')\n }\n\n if (isLastArgCb) {\n if (argsNum < 2) {\n throw new Error('Too few arguments provided')\n }\n\n if (argsNum === 2) {\n cb = text\n text = canvas\n canvas = opts = undefined\n } else if (argsNum === 3) {\n if (canvas.getContext && typeof cb === 'undefined') {\n cb = opts\n opts = undefined\n } else {\n cb = opts\n opts = text\n text = canvas\n canvas = undefined\n }\n }\n } else {\n if (argsNum < 1) {\n throw new Error('Too few arguments provided')\n }\n\n if (argsNum === 1) {\n text = canvas\n canvas = opts = undefined\n } else if (argsNum === 2 && !canvas.getContext) {\n opts = text\n text = canvas\n canvas = undefined\n }\n\n return new Promise(function (resolve, reject) {\n try {\n const data = QRCode.create(text, opts)\n resolve(renderFunc(data, canvas, opts))\n } catch (e) {\n reject(e)\n }\n })\n }\n\n try {\n const data = QRCode.create(text, opts)\n cb(null, renderFunc(data, canvas, opts))\n } catch (e) {\n cb(e)\n }\n}\n\nexports.create = QRCode.create\nexports.toCanvas = renderCanvas.bind(null, CanvasRenderer.render)\nexports.toDataURL = renderCanvas.bind(null, CanvasRenderer.renderToDataURL)\n\n// only svg for now.\nexports.toString = renderCanvas.bind(null, function (data, _, opts) {\n return SvgRenderer.render(data, opts)\n})\n","import { NgView } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { DrawerService } from \"@app/services/drawer.service\";\r\nimport { CrudController } from \"@app/views/crud.view\";\r\nimport { IRootScope } from \"@models\";\r\nimport { StateService } from \"@uirouter/angularjs\";\r\n\r\nexport interface IUserActivationModel {\r\n password?: string;\r\n confirmPassword?: string;\r\n agreedToPrivacyPolicy?: boolean;\r\n}\r\nexport interface IUserActivationScope {\r\n save: () => void;\r\n model: IUserActivationModel;\r\n validation: any;\r\n goToLogin: () => void;\r\n /**\r\n * eUserActivationMode: password or thanks. Sometimes activations require passwords to be reset.\r\n * If so, it will be in the url\r\n */\r\n mode: string;\r\n isNew: boolean;\r\n}\r\n\r\nexport enum eUserActivationMode {\r\n password = \"password\",\r\n thanks = \"thanks\"\r\n}\r\n\r\n@NgView({\r\n token: Token.UserActivationView,\r\n dependencies: [\r\n Token.$Scope,\r\n Token.$RootScope,\r\n Token.DrawerService,\r\n Token.$Http,\r\n Token.$StateParams,\r\n Token.$State\r\n ]\r\n})\r\nexport class UserActivationController {\r\n constructor(\r\n public $scope: IUserActivationScope,\r\n $rootScope: IRootScope,\r\n drawerService: DrawerService,\r\n $http: ng.IHttpService,\r\n $stateParams: any,\r\n $state: StateService\r\n ) {\r\n drawerService.setHelpUrl(null);\r\n\r\n $rootScope.user = {\r\n id: $stateParams.idUser\r\n };\r\n $scope.model = {};\r\n\r\n if ($stateParams.pass && (($stateParams.pass as string).toLowerCase() == \"true\")) {\r\n $scope.mode = eUserActivationMode.password;\r\n $scope.isNew = $stateParams.new && (($stateParams.new as string).toLowerCase() == \"true\");\r\n } else {\r\n $http.post(\r\n \"api/users/activate?idUser=\" + $stateParams.idUser +\r\n \"&activationGuid=\" + $stateParams.activationGuid +\r\n \"&password=\",\r\n { tracker: $rootScope.contentTracker }\r\n ).then(r => {\r\n $scope.mode = eUserActivationMode.thanks;\r\n }, (r: ng.IHttpResponse) => {\r\n $scope.validation = CrudController.prototype.getValidationObject(r.data, r.status);\r\n });\r\n }\r\n \r\n $scope.validation = {};\r\n\r\n $scope.save = () => {\r\n $scope.validation = {};\r\n if ($scope.model.password != $scope.model.confirmPassword) {\r\n $scope.validation.confirmPassword = \"Passwords do not match.\";\r\n }\r\n if ($scope.isNew && !$scope.model.agreedToPrivacyPolicy) {\r\n $scope.validation.agreedToPrivacyPolicy = \"Must agree to the privacy policy\";\r\n }\r\n if ($scope.validation.confirmPassword || $scope.validation.password) return;\r\n var encodePassword = encodeURIComponent($scope.model.password)\r\n return $http.post(\r\n \"api/users/activate?idUser=\" + $stateParams.idUser +\r\n \"&activationGuid=\" + $stateParams.activationGuid +\r\n \"&password=\" + encodePassword +\r\n \"&agreed=\" + $scope.model.agreedToPrivacyPolicy,\r\n { tracker: $rootScope.contentTracker }\r\n ).then(r => {\r\n $scope.mode = eUserActivationMode.thanks;\r\n }, (r: ng.IHttpResponse) => {\r\n $scope.validation = CrudController.prototype.getValidationObject(r.data, r.status);\r\n });\r\n };\r\n\r\n $scope.goToLogin = () => {\r\n window.location.href = \"/\";\r\n };\r\n }\r\n}\r\n","import { NgView } from '@app/di/decorators';\r\nimport { Token } from '@app/di/token';\r\nimport { ClaraViewer, IClaraSceneViewerArgs } from '@app/helpers/clara-viewer';\r\nimport { ConfiguratorHelper } from '@app/helpers/configurator.helper';\r\nimport { Dirs, eBundle } from '@app/helpers/dirs';\r\nimport { Kb3dViewer } from '@app/helpers/kb3d-viewer';\r\nimport { ISceneViewerArgs, SceneViewer } from '@app/helpers/scene-viewer';\r\nimport { ApiService } from '@app/services/api.service';\r\nimport { AuthService } from '@app/services/auth.service';\r\nimport { DialogService } from '@app/services/dialog.service';\r\nimport { DrawerService, IDrawer } from '@app/services/drawer.service';\r\nimport { KbService } from '@app/services/kb.service';\r\nimport { QuoteService } from '@app/services/quote.service';\r\nimport { RuleService } from '@app/services/rule.service';\r\nimport { SfdcService } from '@app/services/sfdc.service';\r\nimport { TelemetryService } from '@app/services/telemetry.service';\r\nimport { ThemeService } from '@app/services/theme.service';\r\nimport { UploadService } from '@app/services/upload.service';\r\nimport { BaseController } from '@app/views/base.view';\r\nimport {\r\n Build,\r\n CToken,\r\n Configurator,\r\n ConfiguratorAction,\r\n DialogButton,\r\n Expander,\r\n Field,\r\n IAlert,\r\n IBuildRuleArgs,\r\n ICompany,\r\n IConfigurator,\r\n IConfiguratorLoadedRuleArgs,\r\n IConfiguratorMessageRuleArgs,\r\n IConfiguratorRuleArgs,\r\n IConfiguratorSession,\r\n IConfiguredProduct,\r\n IExpanderChangedRuleArgs,\r\n IFieldUploadOptions,\r\n IFixThisOption,\r\n IJsResult,\r\n IKb3dCallSceneFunctionArgs,\r\n IKbUser,\r\n IKeyboardArgs,\r\n IKeyboardRuleArgs,\r\n ILayout,\r\n ILoadedRuleArgs,\r\n INestedConfiguratorRuleArgs,\r\n IPriceColumn,\r\n IPriceItem,\r\n IPriceItemBase,\r\n IPriceObject,\r\n IPricingRuleArgs,\r\n IProduct,\r\n IProductTranslation,\r\n IQueue,\r\n IQuote,\r\n IQuoteProduct,\r\n IRootScope,\r\n IScene,\r\n ISceneTranslation,\r\n ISetSceneArgs,\r\n ISfdcCpqPayload,\r\n ITabChangedRuleArgs,\r\n ITable,\r\n ITableObject,\r\n ITestBuild,\r\n ITranslationPackage,\r\n IUploadValue,\r\n InputDialogButton,\r\n KbObject,\r\n KbObjectManager,\r\n LayoutConfig,\r\n NestedSet,\r\n Option,\r\n OptionFilter,\r\n Page,\r\n PropertyChangedEvent,\r\n RuleContainer,\r\n SvgViewer,\r\n TabControl,\r\n UiObject,\r\n Viewer,\r\n eAlertType,\r\n eColumnType,\r\n eEnvironment,\r\n eFormatType,\r\n eNestedSetDisplay,\r\n eRuleType,\r\n eValidationTiming,\r\n eViewType,\r\n eViewerMode,\r\n eWorkflowAction,\r\n} from '@models';\r\nimport { ClientLogger, KPromise } from '@rules';\r\nimport { Color, IMessage, Utils, eScrollMode, icons } from '@tools';\r\nimport { StateParams, StateService } from '@uirouter/angularjs';\r\nimport * as angular from 'angular';\r\nimport { IScope } from 'angular';\r\nimport * as Q from 'q';\r\nimport QRCode from 'qrcode';\r\nimport { InteractionService } from '../../services/interaction.service';\r\n\r\nexport interface ITestBuildDialogScope extends ng.IScope {\r\n model?: {\r\n testBuildName: string;\r\n idQueue: number;\r\n };\r\n queues?: IQueue[];\r\n validation?: {};\r\n}\r\n\r\nexport interface IGenerateQrCodeScope extends IScope {\r\n QrCode?: HTMLCanvasElement;\r\n autoStartAr?: boolean;\r\n updateQrCode?: any;\r\n}\r\n\r\n/**\r\n * Class to help with node & page binding.\r\n * The selected node is what kbTree binds to, and is also what configuratorController\r\n * sets when trying to set the active page through code or the rules. The selected page\r\n * is what drives which page is shown and is not necessarily the same thing.\r\n * There is a special case for nested configurators when they only have one visible page\r\n * (with no visible children of the page) that we try to show the nested configurator as\r\n * one node (instead of a node for the configurator, and another child node for the page).\r\n */\r\nexport class SelectedBinding {\r\n public pageChanged = new PropertyChangedEvent();\r\n\r\n /**\r\n * selected page is the page that is showing. It is not always the selected node in\r\n * the tree though, as there are some special situations to consider (like showing a\r\n * nested config as one node when it only has one visible page).\r\n */\r\n private _page: any;\r\n public get page(): any {\r\n return this._page;\r\n }\r\n /**\r\n * private routine to set the page as consumers should all set the node\r\n * @param newPage\r\n */\r\n private setPage(newPage) {\r\n let oldPage = this._page;\r\n let changed = oldPage !== newPage;\r\n this._page = newPage;\r\n if (changed) this.pageChanged.trigger({ oldValue: oldPage, newValue: newPage, property: 'page' });\r\n }\r\n\r\n /**\r\n * node is bound to the kbTree to track the selected node. All consumers should be setting this\r\n */\r\n private _node: Page | Configurator;\r\n public get node(): Page | Configurator {\r\n return this._node;\r\n }\r\n public set node(newNode) {\r\n if (newNode instanceof Configurator) {\r\n let firstPage = newNode.pages.find(p => p.visible);\r\n if (firstPage) {\r\n newNode = firstPage;\r\n }\r\n }\r\n let oldNode = this._node;\r\n let changed = oldNode !== newNode;\r\n this._node = newNode;\r\n\r\n if (changed) {\r\n let parentConfig = newNode instanceof Configurator ? newNode : newNode.$parentConfigurator;\r\n if (this.isSingleNode(parentConfig)) {\r\n this._node = parentConfig;\r\n this.setPage(newNode);\r\n } else {\r\n this._node = newNode;\r\n this.setPage(newNode);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * if this is the special case where a nested config is shown as a single node because it has only one visible page\r\n * @param tab\r\n */\r\n public isSingleNode(tab: Configurator) {\r\n return (\r\n tab.$parent &&\r\n !tab.pages.some(p => p.pages.some(p2 => p2.visible) || p.configurators.length > 0) &&\r\n tab.pages.filter(p => p.visible).length == 1\r\n );\r\n }\r\n}\r\n\r\nexport interface ITabNode {\r\n id: string;\r\n level: number;\r\n node: Page | Configurator;\r\n}\r\n\r\nexport interface IConfiguratorScope extends ng.IScope {\r\n config: Configurator;\r\n layoutConfig: LayoutConfig;\r\n parentQuote: IQuote;\r\n activeSceneViewer: SceneViewer;\r\n /** dummy term that is useful for re-using the same tab template for pages and configurators */\r\n tab: Configurator;\r\n priceObject: IPriceObject;\r\n pricePrecision: number;\r\n entity: IProduct;\r\n testBuild: (build: Build) => void;\r\n selected: SelectedBinding;\r\n runFixThis: (field: Field, fix: IFixThisOption) => void;\r\n runFieldAction: (field: Field) => void;\r\n runSvgAction: (svg: SvgViewer, $event: MouseEvent) => void;\r\n svgDragStart: (svg: SvgViewer, $event: MouseEvent) => void;\r\n svgDragEnd: (svg: SvgViewer, $event: MouseEvent) => void;\r\n svgDragMove: (svg: SvgViewer, $event: MouseEvent) => void;\r\n runAction: (action: ConfiguratorAction) => ng.IPromise;\r\n actionsVisible: boolean;\r\n fieldValueChange: (field: Field) => ng.IPromise;\r\n fieldTouched: (field: Field) => void;\r\n tabChanged: (oldTab: string, newTab: string, tabControl: TabControl) => void;\r\n expanderChanged: (expander: Expander) => void;\r\n keydown: (event: KeyboardEvent) => void;\r\n nestedTabSelected: (oldTab, newTab: string, field: NestedSet) => void;\r\n nestedSetSelected: (field: NestedSet, nested: Configurator) => void;\r\n togglePages: (show: boolean) => void;\r\n /** whether the pages section is collapsed or not */\r\n showPages: boolean;\r\n pageClick: (e: ng.IAngularEvent, page: Page) => void;\r\n nextPage: () => void;\r\n selectNode: (node: Page | Configurator) => void;\r\n nextNode: Page | Configurator;\r\n backPage: () => void;\r\n backNode: Page | Configurator;\r\n isTest: boolean;\r\n /** the current viewer mode (depends on the settings of the currently selected page, nested scenes, etc) */\r\n viewerMode: string;\r\n /** the path to the media file showing in the viewer (depends on viewer settings in hierarchy of configurators) */\r\n viewerMediaPath: string;\r\n /** nodes calculate for page selection dropdown on mobile */\r\n nodes: ITabNode[];\r\n pageSlideVisible: boolean;\r\n togglePageSlide: (show: boolean) => void;\r\n /** returns if this is a quote product in a workflow, and the user doesn't have permission to modify the product */\r\n isReadOnly: boolean;\r\n isEmbed: boolean;\r\n resizeScene: () => void;\r\n translateKbo: (kbObject: KbObject, property: string) => string;\r\n layoutLoaded: boolean;\r\n\r\n /**\r\n * when a file input field or rules has requested a file upload.\r\n * The callback is called only when the imported file has been returned\r\n * to the client scene and is ready for use\r\n */\r\n upload: (file: File, field: Field) => ng.IPromise;\r\n uploadCleared: (field: Field) => void;\r\n isScene: boolean;\r\n\r\n isNew: boolean;\r\n isEdit: boolean;\r\n isView: boolean;\r\n /** currency might change depending on whether we are in a quote or not */\r\n getCurrency: () => string;\r\n showPricing: (item?: IPriceItemBase) => void;\r\n priceColumns: IPriceColumn[];\r\n priceColumnDb: { [name: string]: IPriceColumn };\r\n\r\n //change display currency for sfdc\r\n sfdcCurrency: string;\r\n sfdcHasCurrency: boolean;\r\n\r\n isKinetic: boolean;\r\n\r\n /** show the moveme animation on loading the scene */\r\n showMove: boolean;\r\n embedCurrency: string;\r\n deferLoadedRule: boolean;\r\n embedFields: {};\r\n embedLayoutSettings: {};\r\n embedParameters: {};\r\n\r\n getSubmitButtonText: () => string;\r\n getSubmitAndStayButtonText: () => string;\r\n getGenerateQrCodeText: () => string;\r\n submitButtonClick: () => ng.IPromise;\r\n\r\n arLoading: ng.IPromiseTracker;\r\n pricingTracker: ng.IPromiseTracker;\r\n\r\n showSpinnerPricing: boolean;\r\n /**\r\n * tracker that only tracks when the user has clicked the price button,\r\n * but we're waiting for the price before showing the dialog\r\n */\r\n priceDialogTracker: ng.IPromiseTracker;\r\n /** a dictionary of configurator id/names organized by the id of the pages they can be added to */\r\n userCanAddToDb: { [idProduct: number]: { [idPage: string]: { id: number; name: string }[] } };\r\n addNestedConfigClick: (e: ng.IAngularEvent, parent: Page | Configurator) => ng.IPromise;\r\n addNestedConfig: (\r\n idNested: number,\r\n parent: Page | Configurator | NestedSet,\r\n addedByUser: boolean,\r\n name?: string\r\n ) => ng.IPromise;\r\n removeNestedConfig: (nested: Configurator) => void;\r\n copyNestedConfig: (sourceConfig: Configurator | Page) => ng.IPromise;\r\n nestedClick: (e: ng.IAngularEvent, nested: Configurator) => void;\r\n\r\n render: () => void;\r\n /** autocomplete field controls asking for updated data */\r\n autoCompleteQuery: (query: string, field: Field) => ng.IPromise;\r\n /** needed for autocompletes that are using the label field to load the initial label to show */\r\n autoCompleteGetLabel: (value: any, field: Field) => ng.IPromise;\r\n\r\n hasChildren: (tab: Page | Configurator) => boolean;\r\n\r\n /** needed for svg filters. See here: http://stackoverflow.com/questions/19742805/angular-and-svg-filters */\r\n absUrl: string;\r\n}\r\n\r\nexport interface IPriceObjectDialogScope extends ng.IScope {\r\n /** named so it can have a consistent name for hierarchy in the view */\r\n item?: IPriceObject;\r\n getCurrency?: () => string;\r\n title?: string;\r\n openItem?: (item) => void;\r\n smartColorStyle?: (level: number) => string;\r\n flat?: boolean;\r\n getColumnValue?: (col: IPriceColumn, item: IPriceItemBase) => string;\r\n infiniteScroll?: () => void;\r\n itemsInView?: IPriceItemBase[];\r\n}\r\n\r\nexport class ConfiguratorRuleArgs implements IConfiguratorRuleArgs, INestedConfiguratorRuleArgs {\r\n constructor(private ctrl: ConfiguratorController) {\r\n this.isMobile = ctrl.$rootScope.windowWidth < Utils.MOBILE_WIDTH;\r\n this.windowWidth = ctrl.$rootScope.windowWidth;\r\n this.windowHeight = ctrl.$rootScope.windowHeight;\r\n }\r\n\r\n public company: ICompany;\r\n public configurator: Configurator;\r\n public layoutConfig: LayoutConfig;\r\n public user: IKbUser;\r\n public kom: KbObjectManager;\r\n public parentKom: KbObjectManager;\r\n public changedField: Field;\r\n public selectedPage: Page;\r\n public nested: Configurator;\r\n public environment: string;\r\n public baseUrl: string;\r\n public parameters: any;\r\n public clientLanguage: string;\r\n public logs: ClientLogger;\r\n public isMobile: boolean;\r\n public windowWidth: number;\r\n public windowHeight: number;\r\n public viewerMode: string;\r\n public isCrm: boolean;\r\n private activeUrl: string = window.location.href;\r\n\r\n public getTables(args): KPromise {\r\n return new KPromise(args.ids.map(tid => this.ctrl.helper.tableArraysDb[tid]));\r\n }\r\n public upload() {\r\n return this.ctrl.uploadService.promptUserToChooseFile().then(file => {\r\n return this.ctrl.$scope.upload(file, null);\r\n });\r\n }\r\n public sendMessage(msg: IMessage) {\r\n // send message to embed consumer\r\n Utils.sendMessageToParent(msg);\r\n\r\n this.ctrl.sfdcService.sendMessage(msg);\r\n }\r\n public callSafeFunction(obj) {\r\n return this.ctrl.api.safeFunctions.run(obj.safeFunctionId, obj.parameters, this.ctrl.$rootScope.contentTracker);\r\n }\r\n public startIntervalFunction(id, timeSeconds) {\r\n return this.ctrl.runContinuousAsyncRule(id, timeSeconds);\r\n }\r\n public stopIntervalFunction(id) {\r\n this.ctrl.cancelScheduledRule(id);\r\n }\r\n public startTimeoutFunction(func, timeSeconds) {\r\n this.ctrl.runTimeoutRule(func, timeSeconds);\r\n }\r\n public convertCurrency(obj) {\r\n return this.ctrl.kbService.fxConvertAsync(obj.amount, obj.currencyCode);\r\n }\r\n public generateNumber(args) {\r\n return this.ctrl.api.generators.next(args.generatorId, this.ctrl.$rootScope.contentTracker);\r\n }\r\n public selectPage(page) {\r\n this.ctrl.$timeout(() => this.ctrl.selectNode(page));\r\n }\r\n public navigateToElement(elem) {\r\n this.ctrl.navigateToElement(elem);\r\n }\r\n public nextPage() {\r\n this.ctrl.$timeout(() => this.ctrl.$scope.nextPage());\r\n }\r\n public backPage() {\r\n this.ctrl.$timeout(() => this.ctrl.$scope.backPage());\r\n }\r\n public runSceneAction(name) {\r\n return this.ctrl.runSceneAction(this.configurator, name);\r\n }\r\n public callSceneFunction(args: IKb3dCallSceneFunctionArgs) {\r\n let sv = this.ctrl.$scope.activeSceneViewer;\r\n if (sv && sv instanceof Kb3dViewer) {\r\n return sv.runSceneFunction(args, this.configurator).then(r => r.parameters.returnValue);\r\n }\r\n\r\n console.warn(`Scene function ${args.name} was called but a scene is not loaded.`);\r\n return Promise.resolve(null);\r\n }\r\n public setScene(args: ISetSceneArgs): ng.IPromise {\r\n return this.ctrl.setScene(this.configurator, args.idScene);\r\n }\r\n public runNamingRule() {\r\n return this.ctrl.helper.runRuleTypeAsync(this.configurator, eRuleType.naming);\r\n }\r\n public addNestedConfigurator(idProduct, idParent, name?: string, fields?: {}) {\r\n // this call already came from a rule, so we don't need to run the oncePerRuleCycle here\r\n return this.ctrl.addNestedConfig(\r\n idProduct,\r\n this.configurator.$manager.get(idParent) as Page | Configurator | NestedSet,\r\n false,\r\n name,\r\n fields\r\n );\r\n }\r\n public copyNestedConfigurator(nested: Configurator | string, idParent, name?: string) {\r\n let sourceConfig: Configurator = nested as Configurator;\r\n if (angular.isString(nested)) {\r\n sourceConfig = this.configurator.$manager.getByName(nested as string, false);\r\n }\r\n return this.ctrl.copyNestedConfig(\r\n sourceConfig,\r\n this.configurator.$manager.get(idParent) as Page | Configurator | NestedSet,\r\n false,\r\n name\r\n );\r\n }\r\n public setNumberOfNestedConfigurators(idProduct, idParent, n) {\r\n return this.ctrl.setNumberOfNestedConfigs(\r\n idProduct,\r\n this.configurator.$manager.get(idParent) as Page | Configurator | NestedSet,\r\n n\r\n );\r\n }\r\n public removeNestedConfigurator(nested: Configurator | string) {\r\n let nestedConfig: Configurator = nested as Configurator;\r\n if (angular.isString(nested)) {\r\n nestedConfig = this.configurator.$manager.getByName(nested as string, false);\r\n }\r\n return this.ctrl.removeNestedConfig(nestedConfig);\r\n }\r\n public showPriceDetails() {\r\n this.ctrl.$scope.showPricing();\r\n }\r\n public alert(args: IAlert) {\r\n this.ctrl.dialogService.alert(args);\r\n }\r\n public getOptionFilterSource(idOptionFilter: string, fromConfigurator?: Configurator) {\r\n fromConfigurator = fromConfigurator || this.configurator;\r\n let f = fromConfigurator.$manager.get(idOptionFilter) as OptionFilter;\r\n return new KPromise(f ? f.$source : []);\r\n }\r\n public setLayoutSetting(id: string, value: any) {\r\n if (!this.configurator.isNested()) {\r\n //nested configurators should not be able to override the root's layout settings\r\n let s = this.layoutConfig.$manager.getByIdOrName(id, true);\r\n let origValue = s.value;\r\n s.value = value;\r\n if (origValue != s.value) {\r\n this.layoutConfig.$layoutSettingsDirty = true;\r\n }\r\n }\r\n }\r\n public getLayoutSetting(id: string) {\r\n let s = this.layoutConfig.$manager.getByIdOrName(id, true);\r\n return s.value;\r\n }\r\n public toggleFullscreen() {\r\n this.ctrl.$rootScope.toggleFullscreen();\r\n }\r\n public runConfiguredProduct(configProd: IConfiguredProduct) {\r\n //run the configured product after this rule has ended\r\n this.ctrl.runConfiguredProduct(this.configurator, configProd);\r\n }\r\n}\r\n\r\nexport class SvgRuleArgs extends ConfiguratorRuleArgs {\r\n public elementId: string;\r\n public mouseX: number;\r\n public mouseY: number;\r\n public commitDrag: boolean;\r\n public originMouseX: number;\r\n public originMouseY: number;\r\n public originElementId: string;\r\n}\r\n\r\n@NgView({\r\n token: Token.ConfiguratorView,\r\n dependencies: [\r\n Token.$Scope,\r\n Token.$Q,\r\n Token.$Location,\r\n Token.$State,\r\n Token.$StateParams,\r\n Token.$Http,\r\n Token.$RootScope,\r\n Token.$Window,\r\n Token.$Compile,\r\n Token.$Injector,\r\n Token.DialogService,\r\n Token.$Timeout,\r\n Token.$Interval,\r\n Token.$Filter,\r\n Token.DrawerService,\r\n Token.RuleService,\r\n Token.UploadService,\r\n Token.AuthService,\r\n Token.QuoteService,\r\n Token.PromiseTracker,\r\n Token.ApiService,\r\n Token.ThemeService,\r\n Token.SfdcService,\r\n Token.KbService,\r\n Token.TelemetryService,\r\n Token.InteractionService,\r\n Token.$OcLazyLoad,\r\n ],\r\n})\r\nexport class ConfiguratorController extends BaseController {\r\n constructor(\r\n public $scope: IConfiguratorScope,\r\n public $q: ng.IQService,\r\n public $location: ng.ILocationService,\r\n public $state: StateService,\r\n public $stateParams: StateParams,\r\n public $http: ng.IHttpService,\r\n public $rootScope: IRootScope,\r\n public $window: ng.IWindowService,\r\n public $compile: ng.ICompileService,\r\n public $injector: ng.auto.IInjectorService,\r\n public dialogService: DialogService,\r\n public $timeout: ng.ITimeoutService,\r\n public $interval: ng.IIntervalService,\r\n public $filter: ng.IFilterService,\r\n public drawerService: DrawerService,\r\n public ruleService: RuleService,\r\n public uploadService: UploadService,\r\n public authService: AuthService,\r\n public quoteService: QuoteService,\r\n public promiseTracker: ng.IPromiseTracker,\r\n public api: ApiService,\r\n public themeService: ThemeService,\r\n public sfdcService: SfdcService,\r\n public kbService: KbService,\r\n public telemetryService: TelemetryService,\r\n public interactionService: InteractionService,\r\n public ocLazyLoad: oc.ILazyLoad\r\n ) {\r\n super();\r\n\r\n this.model = {};\r\n this.configuratorLoadedDeferred = this.$q.defer();\r\n this.$scope.layoutLoaded = false;\r\n this.$rootScope.contentTracker.addPromise(this.configuratorLoadedDeferred.promise);\r\n let isScene = ($scope.isScene = $state.current.name == 'scene');\r\n let queryString = $location.search();\r\n\r\n $scope.isTest = false;\r\n if ($state.current.data) {\r\n $scope.isEdit = $state.current.data.viewType == eViewType.edit;\r\n $scope.isNew = $state.current.data.viewType == eViewType.new;\r\n $scope.isView = $state.current.data.viewType == eViewType.view;\r\n $scope.isTest = $state.current.data.isTest == true;\r\n }\r\n if ($scope.isTest) {\r\n this.drawerService.setHelpUrl('Configurators');\r\n } else {\r\n this.drawerService.setHelpUrl(null);\r\n }\r\n\r\n // setup binding to handle selected page and node\r\n $scope.selected = new SelectedBinding();\r\n\r\n $scope.pricingTracker = promiseTracker();\r\n $scope.priceDialogTracker = promiseTracker();\r\n $scope.arLoading = promiseTracker();\r\n $scope.showSpinnerPricing = true;\r\n\r\n // $scope.showConfigHeader = (queryString.showconfigheader != \"false\");\r\n // $scope.showFields = (queryString.showfields != \"false\");\r\n $scope.showMove = queryString.showmove == 'true';\r\n $scope.isEmbed = Utils.isDefined(queryString.embedded);\r\n $scope.embedFields = queryString['fields'] ? JSON.parse(queryString['fields']) : null;\r\n $scope.embedLayoutSettings = queryString['layoutsettings'] ? JSON.parse(queryString['layoutsettings']) : null;\r\n $scope.embedParameters = queryString['parameters'] ? JSON.parse(queryString['parameters']) : null;\r\n $scope.embedCurrency = queryString['currency'];\r\n $scope.deferLoadedRule = queryString['deferLoadedRule'] == 'true';\r\n $scope.isKinetic = !!queryString['kineticCompany'];\r\n\r\n // only allow the embed currency if it's a defined company currency\r\n if (!this.$rootScope.companyCurrencies.some(c => c.currency == $scope.embedCurrency)) {\r\n $scope.embedCurrency = null;\r\n }\r\n $scope.actionsVisible = true;\r\n $scope.absUrl = $location.absUrl();\r\n $scope.isReadOnly = false;\r\n\r\n if ($scope.isEmbed) {\r\n $rootScope.hideDrawer = queryString.showdrawer != 'true';\r\n $rootScope.transparentBackground = queryString.transparentbackground == 'true';\r\n }\r\n\r\n if (Utils.isDefined(queryString.showheader) && queryString.showheader == 'false') {\r\n $rootScope.hideHeader = true;\r\n }\r\n\r\n this.requestId = queryString.requestid;\r\n\r\n this.helper = new ConfiguratorHelper({\r\n $http: this.$http,\r\n $q: this.$q,\r\n api: this.api,\r\n dialogService: this.dialogService,\r\n ruleService: this.ruleService,\r\n tracker: this.$rootScope.contentTracker,\r\n $rootScope: this.$rootScope,\r\n getRuleArgs: (c, f) => this.getRuleArgs(c, f),\r\n showErrors: () => this.showErrors(),\r\n });\r\n\r\n $scope.translateKbo = (o, prop) => {\r\n if (o) {\r\n if (this.$rootScope.companySettings.defaultLanguage != this.$rootScope.clientLanguage) {\r\n var parentConfig = o instanceof Configurator ? o : o.$parentConfigurator;\r\n var configDb = this.translationDb[parentConfig.idProduct || parentConfig.idScene];\r\n if (configDb && configDb.hasOwnProperty(o.id) && configDb[o.id].hasOwnProperty(prop)) {\r\n return configDb[o.id][prop];\r\n }\r\n }\r\n var realProp = prop == 'name' ? '$label' : prop;\r\n return o[realProp];\r\n }\r\n return '';\r\n };\r\n\r\n this.getConfigurator().then(rootConfig => {\r\n if (rootConfig == null) return;\r\n this.rootConfig = $scope.config = $scope.tab = rootConfig;\r\n\r\n this.interactionService.record(this.rootConfig.idProduct);\r\n\r\n $scope.selected.pageChanged.add(args => {\r\n // run the pageChanged rule\r\n let pageParentConfig = args.newValue.$parentConfigurator;\r\n let pageChangedArgs = this.getRuleArgs(pageParentConfig);\r\n pageChangedArgs.selectedPage = args.newValue;\r\n if (window.location.href.includes('ar=true')) {\r\n this.enterArModal();\r\n }\r\n this.trackConfigPageView(pageChangedArgs.selectedPage);\r\n this.queueRule(() => {\r\n return this.helper\r\n .runRuleTypeAsync(pageParentConfig, eRuleType.pageChanged, pageChangedArgs)\r\n .then(r => {\r\n // make sure all nodes are expanded\r\n if (args.newValue) {\r\n let parent: KbObject = args.newValue;\r\n while (parent) {\r\n parent.$expanded = true;\r\n parent = parent.$parent;\r\n }\r\n }\r\n if (!this.loading && pageParentConfig.getRuleJs(eRuleType.pageChanged)) {\r\n return this.runRuleCycleUnit(pageParentConfig, null).then(() =>\r\n this.oncePerCycleRule()\r\n );\r\n } else {\r\n // refresh viewer so we can change scenes for\r\n // nested configurators with scenes that aren't nesting\r\n this.getCurrentConfigForViewerAndSetViewerMode(); //set the viewermode before layout rule so it can show/hide the viewer accordingly\r\n return this.runLayoutRule(\r\n this.$scope.config,\r\n this.getRuleArgs(this.$scope.config)\r\n ).then(() => {\r\n return this.refreshViewer(true).then(() => {\r\n // even if not running the value rule, we still need to\r\n // update the nodes for the next / back buttons\r\n this.calculateNodes();\r\n });\r\n });\r\n }\r\n });\r\n });\r\n });\r\n\r\n $scope.testBuild = (build: Build) => {\r\n this.runSubmitRule().then(() => {\r\n this.helper.runRuleTypeAsync(this.rootConfig, eRuleType.naming);\r\n let buildRuleArgs: IBuildRuleArgs = this.getRuleArgs(this.rootConfig) as any;\r\n buildRuleArgs.build = build;\r\n buildRuleArgs.quote = {\r\n name: 'Test Quote',\r\n id: 1,\r\n ownedBy: this.$rootScope.user.id,\r\n owner: this.$rootScope.user.firstName + ' ' + this.$rootScope.user.lastName,\r\n description: '',\r\n currency: 'USD',\r\n };\r\n buildRuleArgs.quoteProduct = {\r\n isConfigured: true,\r\n id: 1,\r\n qty: 1,\r\n priceObject: this.$scope.priceObject,\r\n name: this.rootConfig.name,\r\n description: this.rootConfig.description,\r\n shortDescription: this.rootConfig.shortDescription,\r\n };\r\n\r\n let displayDialog = (queueId: number) => {\r\n let dialogScope: ITestBuildDialogScope = $rootScope.$new();\r\n dialogScope.model = {\r\n testBuildName: this.rootConfig.name + ' ' + build.name + ' Test Build',\r\n idQueue: queueId,\r\n };\r\n dialogScope.validation = {};\r\n api.queues.search().then(r => (dialogScope.queues = r));\r\n\r\n dialogService.dialog({\r\n template: Dirs.view('dialog-test-build'),\r\n scope: dialogScope,\r\n buttons: [\r\n new InputDialogButton(loc.ok, icons.success, args => {\r\n if (!dialogScope.model.testBuildName) {\r\n dialogScope.validation['testBuildName'] = 'Name is required';\r\n args.close = false;\r\n return;\r\n }\r\n if (dialogScope.model.testBuildName.length > 400) {\r\n dialogScope.validation['testBuildName'] =\r\n 'Name must be less than 400 characters';\r\n args.close = false;\r\n return;\r\n }\r\n this.api.testBuilds\r\n .insert(\r\n {\r\n idBuildType: build.idBuildType,\r\n idProduct: parseInt($state.params.id, 10),\r\n name: dialogScope.model.testBuildName,\r\n idQueue: dialogScope.model.idQueue,\r\n configuredProduct: this.rootConfig.getConfiguredProduct(),\r\n cloudBuild: build.cloudBuild,\r\n priceObject: this.$scope.priceObject,\r\n } as ITestBuild,\r\n this.$rootScope.contentTracker\r\n )\r\n .then(testBuild => {\r\n dialogService.confirm(\r\n 'Your configurator is building ' +\r\n build.name +\r\n ' outputs. Would you like to go to the test build page?',\r\n () => {\r\n $state.go('kb.admin.testBuild', { id: testBuild.id });\r\n }\r\n );\r\n });\r\n }),\r\n new InputDialogButton(loc.cancel, icons.cancel, args => {}),\r\n ],\r\n });\r\n };\r\n\r\n try {\r\n this.helper\r\n .runRuleContainerAsync(\r\n build.ruleContainers.find(rc => rc.ruleType == eRuleType.beforeBuild),\r\n buildRuleArgs\r\n )\r\n .then(\r\n (result: IJsResult) => {\r\n let queueId = result.parameters.build.idQueue;\r\n displayDialog(queueId);\r\n },\r\n () => {\r\n // We'll want to display the dialog even if this rule fails,\r\n // since it's possible it's due to functionality that's only available in server-side rules.\r\n displayDialog(build.idQueue);\r\n }\r\n );\r\n } catch (e) {\r\n // We'll want to display the dialog even if this rule fails, since it's possible it's due to\r\n // functionality that's only available in server-side rules.\r\n displayDialog(build.idQueue);\r\n }\r\n });\r\n };\r\n\r\n $scope.getSubmitButtonText = () => {\r\n return this.$scope.config.submitButtonText ? this.$scope.config.submitButtonText : loc.addtoquote;\r\n };\r\n\r\n $scope.getSubmitAndStayButtonText = () => {\r\n return this.$scope.config.submitAndStayButtonText\r\n ? this.$scope.config.submitAndStayButtonText\r\n : loc.saveandstay;\r\n };\r\n\r\n $scope.getGenerateQrCodeText = () => {\r\n return this.$scope.config.generateQrCodeText\r\n ? this.$scope.config.generateQrCodeText\r\n : loc.generateqrcode;\r\n };\r\n\r\n $scope.submitButtonClick = () => {\r\n if ($scope.isEmbed) {\r\n Utils.sendMessageToParent({ name: 'submit', data: {} });\r\n } else {\r\n return this.submit();\r\n }\r\n };\r\n\r\n $scope.runFixThis = (field: Field, fix: IFixThisOption) => {\r\n return this.queueRule(() => {\r\n return (new KPromise(fix.fix()) as any as ng.IPromise)\r\n .then(() => this.runRuleCycleUnit(field.$parentConfigurator, null))\r\n .then(() => this.oncePerCycleRule());\r\n });\r\n };\r\n\r\n let getTargetElementId = ($event: MouseEvent) => {\r\n let el = $event.target;\r\n let elementId = el.id;\r\n while (!elementId && el) {\r\n if (el.tagName == 'svg') break;\r\n elementId = el.id;\r\n el = el.parentElement;\r\n }\r\n return elementId;\r\n };\r\n\r\n let getSvgArgs = (svgViewer, $event: MouseEvent, $originalStartEvent: MouseEvent = null): SvgRuleArgs => {\r\n let c = svgViewer.$parentConfigurator;\r\n let args: any = this.getRuleArgs(c) as SvgRuleArgs;\r\n args.elementId = getTargetElementId($event);\r\n args.mouseX = $event.offsetX;\r\n args.mouseY = $event.offsetY;\r\n args.commitDrag = false;\r\n\r\n if ($originalStartEvent) {\r\n args.originMouseX = $originalStartEvent.offsetX;\r\n args.originMouseY = $originalStartEvent.offsetY;\r\n args.originElementId = getTargetElementId($originalStartEvent);\r\n }\r\n return args;\r\n };\r\n\r\n $scope.runSvgAction = (svgViewer, $event: MouseEvent) => {\r\n let rc = svgViewer.ruleContainers.find(rc => rc.ruleType == eRuleType.svgViewer);\r\n if (rc) {\r\n let args = getSvgArgs(svgViewer, $event);\r\n return this.queueEventRule(svgViewer.$parentConfigurator, rc, args);\r\n }\r\n };\r\n\r\n let originalDragStartEvent: MouseEvent = null;\r\n let svgViewerShouldEnablePanAfterDrag = false;\r\n $scope.svgDragStart = (svgViewer, $event: MouseEvent) => {\r\n let rc = svgViewer.ruleContainers.find(r => r.ruleType == eRuleType.dragStart);\r\n if (rc) {\r\n let args = getSvgArgs(svgViewer, $event, originalDragStartEvent);\r\n return this.helper.runRuleContainerAsync(rc, args).then(result => {\r\n if (!result.hasError && result.parameters.commitDrag) {\r\n originalDragStartEvent = $event;\r\n svgViewerShouldEnablePanAfterDrag = !svgViewer.disablePan;\r\n svgViewer.disablePan = true;\r\n }\r\n });\r\n }\r\n };\r\n\r\n $scope.svgDragMove = (svgViewer, $event: MouseEvent) => {\r\n if (originalDragStartEvent) {\r\n let rc = svgViewer.ruleContainers.find(r => r.ruleType == eRuleType.dragMove);\r\n if (rc) {\r\n let args = getSvgArgs(svgViewer, $event, originalDragStartEvent);\r\n return this.helper.runRuleContainerAsync(rc, args).then(() => $scope.$digest());\r\n }\r\n }\r\n };\r\n\r\n $scope.svgDragEnd = (svgViewer, $event: MouseEvent) => {\r\n if (originalDragStartEvent) {\r\n let rc = svgViewer.ruleContainers.find(r => r.ruleType == eRuleType.dragEnd);\r\n if (rc) {\r\n let args = getSvgArgs(svgViewer, $event, originalDragStartEvent);\r\n originalDragStartEvent = null;\r\n svgViewer.disablePan = !svgViewerShouldEnablePanAfterDrag;\r\n return this.queueEventRule(svgViewer.$parentConfigurator, rc, args);\r\n }\r\n }\r\n };\r\n\r\n $scope.runFieldAction = field => {\r\n if (isScene) {\r\n return this.$scope.activeSceneViewer && this.$scope.activeSceneViewer.runFieldAction(field);\r\n } else {\r\n return this.queueEventRule(\r\n field.$parentConfigurator,\r\n field,\r\n this.getRuleArgs(field.$parentConfigurator)\r\n );\r\n }\r\n };\r\n\r\n $scope.runAction = action => {\r\n if (isScene) {\r\n return this.queueRule(() => this.runSceneAction(this.rootConfig, action.name));\r\n } else {\r\n return this.queueEventRule(\r\n action.$parentConfigurator,\r\n action,\r\n this.getRuleArgs(action.$parentConfigurator)\r\n );\r\n }\r\n };\r\n\r\n $scope.fieldValueChange = field => {\r\n if (!this.loading) {\r\n return this.queueRule(() => {\r\n return this.helper\r\n .runRuleContainerAsync(field)\r\n .then(() => this.runRuleCycleUnit(field.$parentConfigurator, field))\r\n .then(() => this.oncePerCycleRule());\r\n });\r\n }\r\n };\r\n\r\n $scope.fieldTouched = field => {\r\n field.hasBeenTouched = true;\r\n if (field.$parentConfigurator.validationTiming == eValidationTiming.onTouched) {\r\n this.rootConfig.isValid(); //recalculate root as the field might be in a nested set, which is in a page, etc.\r\n }\r\n };\r\n\r\n $scope.tabChanged = (oldTab, newTab, tabControl) => {\r\n if (!this.loading) {\r\n let c = tabControl.$parentConfigurator;\r\n let args: ITabChangedRuleArgs = this.getRuleArgs(c) as any;\r\n args.oldTab = c.$manager.getByName(oldTab, false);\r\n args.newTab = c.$manager.getByName(newTab, false);\r\n args.tabControl = tabControl;\r\n let origNumberOfNesteds = c.getNestedConfigurators().length;\r\n\r\n return this.queueEventRuleType(c, eRuleType.tabChanged, args);\r\n }\r\n };\r\n\r\n $scope.keydown = (k: KeyboardEvent) => {\r\n if (\r\n !(\r\n k.target instanceof HTMLInputElement ||\r\n k.target instanceof HTMLTextAreaElement ||\r\n (k.target instanceof HTMLElement && k.target.classList.contains('kb-no-keyboard-rule'))\r\n )\r\n ) {\r\n let keyArgs = {\r\n event: k,\r\n key: k.key,\r\n keyCode: k.keyCode,\r\n altKey: k.altKey,\r\n ctrlKey: k.ctrlKey || k.metaKey,\r\n shiftKey: k.shiftKey,\r\n repeat: k.repeat,\r\n } as IKeyboardArgs;\r\n\r\n let ruleArgs: IKeyboardRuleArgs = this.getRuleArgs($scope.config) as any;\r\n ruleArgs.keyArgs = keyArgs;\r\n\r\n return this.queueEventRuleType($scope.config, eRuleType.keyboard, ruleArgs);\r\n }\r\n };\r\n\r\n $scope.expanderChanged = expander => {\r\n if (!this.loading) {\r\n let c = expander.$parentConfigurator;\r\n let args: IExpanderChangedRuleArgs = this.getRuleArgs(c) as any;\r\n args.expander = expander;\r\n let origNumberOfNesteds = c.getNestedConfigurators().length;\r\n\r\n return this.queueEventRuleType(c, eRuleType.expanderChanged, args);\r\n }\r\n };\r\n\r\n $scope.nestedTabSelected = (oldTab, nestedName, nestedSet: NestedSet) => {\r\n let newTab = nestedSet.$parentConfigurator.$manager.getByName(nestedName, false);\r\n return $scope.nestedSetSelected(nestedSet, newTab);\r\n };\r\n\r\n $scope.nestedSetSelected = (nestedSet: NestedSet, nested: Configurator) => {\r\n if (!this.loading) {\r\n let c = nested;\r\n let args: INestedConfiguratorRuleArgs = this.getRuleArgs(nestedSet.$parentConfigurator) as any;\r\n args.nested = c;\r\n let parentConfig = c.$parentConfigurator;\r\n return this.queueEventRule(nestedSet.$parentConfigurator, nestedSet, args);\r\n }\r\n };\r\n\r\n $scope.togglePages = show => {\r\n let changed = $scope.showPages != show;\r\n $scope.showPages = show;\r\n if (changed) {\r\n $scope.resizeScene();\r\n this.refreshDrawer();\r\n }\r\n };\r\n\r\n $scope.resizeScene = () => {\r\n if ($scope.activeSceneViewer) {\r\n $timeout(() => {\r\n $timeout(() => {\r\n $scope.activeSceneViewer.resize();\r\n $scope.activeSceneViewer.refreshElementParent();\r\n });\r\n }, 0);\r\n }\r\n };\r\n\r\n $scope.pageClick = (e, page: Page) => {\r\n e.stopPropagation();\r\n $scope.togglePages(true);\r\n };\r\n\r\n $scope.nextPage = () => {\r\n if (this.$scope.nextNode) this.selectNode(this.$scope.nextNode);\r\n };\r\n\r\n $scope.backPage = () => {\r\n if (this.$scope.backNode) this.selectNode(this.$scope.backNode);\r\n };\r\n\r\n $scope.nestedClick = (e, nested) => {\r\n e.stopPropagation();\r\n this.selectNode(nested);\r\n // var firstPage = nested.pages.find(p => p.visible);\r\n // if (firstPage) {\r\n // this.selectNode(firstPage);\r\n // }\r\n };\r\n\r\n $scope.hasChildren = tab => {\r\n if (tab instanceof Configurator && $scope.selected.isSingleNode(tab)) {\r\n return tab.configurators.length > 0;\r\n } else {\r\n return tab.pages.some(p => p.visible) || tab.configurators.length > 0;\r\n }\r\n };\r\n\r\n let thisCtrl = this;\r\n\r\n $scope.upload = function (file, field: Field) {\r\n let uploadOptions = {\r\n convertPdfToImage: field.convertUploadPdfToImage,\r\n } as IFieldUploadOptions;\r\n return thisCtrl.uploadService.uploadConfiguredProductFile(file, uploadOptions).then(uuid => {\r\n let uploadValue = field.value as IUploadValue;\r\n uploadValue.path = uuid;\r\n field.$parentConfigurator.$fieldsDirty = true;\r\n field.$parentConfigurator.$fieldsDirtyForSceneRules = true;\r\n // clear the asset id in case there was an old file there that was just\r\n // replaced to make sure the new file is uploaded to the scene\r\n uploadValue.assetId = null;\r\n if (thisCtrl.$scope.activeSceneViewer && thisCtrl.$scope.activeSceneViewer.scene.external) {\r\n let sceneUploadPromise = thisCtrl.$scope.activeSceneViewer.importUploadFieldImage(\r\n field.$parentConfigurator,\r\n field,\r\n file\r\n );\r\n thisCtrl.$rootScope.contentTracker.addPromise(sceneUploadPromise);\r\n return sceneUploadPromise;\r\n }\r\n });\r\n };\r\n\r\n $scope.uploadCleared = (field: Field) => {\r\n field.$parentConfigurator.$fieldsDirty = true;\r\n field.$parentConfigurator.$fieldsDirtyForSceneRules = true;\r\n };\r\n\r\n $scope.getCurrency = () => {\r\n // if there is a quote, then that overrides everything\r\n if ($scope.parentQuote) {\r\n return $scope.parentQuote.currency;\r\n } else if (quoteService.quote) {\r\n return quoteService.quote.currency;\r\n } else {\r\n //if this is an sfdc cpq, use the incoming currency if provided\r\n if (this.$scope.sfdcHasCurrency) {\r\n //console.log(this.$rootScope.context.sfdcConvertCurrency ?? 'convert currency not set');\r\n return this.$scope.sfdcCurrency;\r\n }\r\n // if we are in an embed, and the embed currency was specified, then use it\r\n if (this.$scope.isEmbed && this.$scope.embedCurrency) {\r\n return this.$scope.embedCurrency;\r\n } else {\r\n // just use the default company currency\r\n return this.$rootScope.companySettings.currency;\r\n }\r\n }\r\n };\r\n\r\n $scope.showPricing = (item?: IPriceItemBase) => {\r\n if (this.lastPricingPromise) {\r\n this.$scope.priceDialogTracker.addPromise(this.lastPricingPromise);\r\n this.lastPricingPromise.then(() => {\r\n let dialogScope: IPriceObjectDialogScope = $scope.$new();\r\n dialogScope.itemsInView = [];\r\n dialogScope.item = item || $scope.priceObject;\r\n this.addLevelsToPricing(dialogScope.item);\r\n dialogScope.flat =\r\n dialogScope.item.items && !dialogScope.item.items.some(i => i.items.length > 0);\r\n dialogScope.getCurrency = $scope.getCurrency;\r\n dialogScope.title = (item ? (item as IPriceItem).sku : this.rootConfig.name) + ' Pricing';\r\n dialogScope.getColumnValue = (col, item) => {\r\n let val = col.systemColumn\r\n ? item[col.name.toCamelCase()]\r\n : item.columns[col.name.toCamelCase()];\r\n\r\n let format = col.format;\r\n if (col.name.isEqual('discount')) {\r\n if ((item.useRollup && item.items && item.items.length) || item.discountType == '$') {\r\n val = item.totalDiscount;\r\n format = eFormatType.currency;\r\n } else {\r\n format = eFormatType.percentage;\r\n }\r\n }\r\n if (col.type == eColumnType.number) {\r\n const minPrecision = Number(col.formatMinPrecision);\r\n const precision = Number(col.precision);\r\n if (format == eFormatType.currency && precision === 2 && minPrecision === 2) {\r\n val = $filter('fxConvert')(val, $scope.getCurrency());\r\n } else {\r\n if (format == eFormatType.currency) {\r\n val = kbService.fxConvert(val, $scope.getCurrency());\r\n }\r\n\r\n val = Number(val).format({\r\n formatType: format,\r\n minPrecision: minPrecision,\r\n maxPrecision: precision,\r\n currency: $scope.getCurrency(),\r\n decimalSeparator: col.formatDecimalSeparator,\r\n thousandsSeparator: col.formatThousandsSeparator,\r\n prefix: col.formatPrefix,\r\n suffix: col.formatSuffix,\r\n });\r\n }\r\n }\r\n return val;\r\n };\r\n dialogScope.openItem = (nestedItem: IPriceItem) => {\r\n // $scope.showPricing(nestedItem)\r\n (nestedItem as any).$expanded = !(nestedItem as any).$expanded;\r\n };\r\n dialogScope.smartColorStyle = level => {\r\n let background = new Color(this.themeService.getActiveTheme().background);\r\n if (level) {\r\n if (background.isDark()) {\r\n background = Color.lighten(background.getOriginalInput(), level * 6);\r\n } else {\r\n background = Color.darken(background.getOriginalInput(), level * 6);\r\n }\r\n }\r\n let color = background.isDark() ? 'white' : 'black';\r\n return 'background: ' + background.toRgbString() + '; color: ' + color + ';';\r\n };\r\n dialogScope.infiniteScroll = () => {\r\n let pageSize = 50;\r\n let totalCount = $scope.priceObject.items.length;\r\n let currCount = dialogScope.itemsInView.length;\r\n if (totalCount > currCount) {\r\n let i = currCount;\r\n if (i < 0) i = 0;\r\n dialogScope.itemsInView.pushArray($scope.priceObject.items.slice(i, i + 50));\r\n }\r\n };\r\n dialogScope.infiniteScroll();\r\n dialogService.dialog({\r\n fullHeight: true,\r\n template: Dirs.view('dialog-price-object'),\r\n scope: dialogScope,\r\n buttons: [\r\n new DialogButton(loc.close, icons.cancel, args => {\r\n if ($scope.isEmbed) {\r\n Utils.sendMessageToParent({ name: 'pricingDetailsClosed', data: {} });\r\n }\r\n }),\r\n ],\r\n });\r\n\r\n if ($scope.isEmbed) {\r\n Utils.sendMessageToParent({ name: 'pricingDetailsShown', data: {} });\r\n }\r\n });\r\n }\r\n };\r\n\r\n $scope.addNestedConfigClick = (e, parent) => {\r\n // if the parent only has one type of referenced configurator, then we add it\r\n // if more than 1 ref config, then let control pass to the dropdown\r\n let parentConfig =\r\n parent instanceof Configurator ? (parent as Configurator) : parent.$parentConfigurator;\r\n let entries = $scope.userCanAddToDb[parentConfig.idProduct][parent.id];\r\n if (entries && entries.length == 1) {\r\n e.stopPropagation();\r\n return $scope.addNestedConfig(entries[0].id, parent, true);\r\n }\r\n return new KPromise(null) as any;\r\n };\r\n\r\n $scope.addNestedConfig = (idNested, parent, addedByUser, name) => {\r\n return this.addNestedConfig(idNested, parent, addedByUser, name).then((config: Configurator) => {\r\n return this.runRuleCycleUnit(config.$parentConfigurator, null).then(() =>\r\n this.oncePerCycleRule().then(() => config)\r\n );\r\n });\r\n };\r\n\r\n $scope.copyNestedConfig = source => {\r\n let sourceConfig =\r\n source instanceof Configurator ? (source as Configurator) : source.$parentConfigurator;\r\n\r\n return this.copyNestedConfig(sourceConfig, sourceConfig.$parent as any, true).then(target =>\r\n this.nestedRunBottomsUp(target, c => this.runRuleCycleUnit(c, null))\r\n );\r\n };\r\n\r\n $scope.removeNestedConfig = nested => {\r\n // might be a page or configurator passed in. If it's a page,\r\n // it's the page's parent configurator that needs to be deleted\r\n if (nested instanceof Page || nested instanceof NestedSet)\r\n nested = (nested as Page).$parentConfigurator as Configurator;\r\n\r\n this.dialogService.confirm(\"Are you sure you want to remove the item '\" + nested.name + \"'?\", () =>\r\n this.removeNestedConfig(nested).then(() => {\r\n let parentConfig =\r\n nested.$parent instanceof Configurator\r\n ? (nested.$parent as Configurator)\r\n : nested.$parent.$parentConfigurator;\r\n return this.runRuleCycleUnit(parentConfig, null).then(() => this.oncePerCycleRule());\r\n })\r\n );\r\n };\r\n\r\n $scope.autoCompleteQuery = (query, field) => {\r\n return this.helper.autoCompleteQuery(query, field);\r\n };\r\n $scope.autoCompleteGetLabel = (value, field) => {\r\n return this.helper.autoCompleteGetLabel(value, field);\r\n };\r\n\r\n $scope.togglePageSlide = show => {\r\n $scope.pageSlideVisible = show;\r\n };\r\n\r\n $scope.selectNode = node => {\r\n this.selectNode(node);\r\n };\r\n\r\n // $scope.render = () => {\r\n // if (this.$scope.sceneViewer) {\r\n\r\n // var promise = this.$scope.sceneViewer.render().then((url) => {\r\n // this.rootConfig.viewerMediaPath = url;\r\n // });\r\n\r\n // this.dialogService && this.dialogService.alert({\r\n // msg: \"Your rendering is being processed\",\r\n // persist: false,\r\n // timeShown: 1,\r\n // promise: promise\r\n // });\r\n\r\n // return promise;\r\n // }\r\n\r\n // return $q.when(null);\r\n // };\r\n\r\n // when used in an iframe, we need to catch messages posted from the outside world to respond\r\n let messageHandler = event => {\r\n let msg: IMessage = event.data;\r\n if (msg) {\r\n let data = msg.data;\r\n if (msg.name) {\r\n let messageName = msg.name.toLowerCase();\r\n if (messageName == 'setfields') {\r\n $scope.$apply(() => {\r\n this.queueRule(() => {\r\n $scope.config.setFields(data);\r\n return this.runRuleCycleUnit($scope.config, null)\r\n .then(() => this.oncePerCycleRule())\r\n .then(() => {\r\n Utils.sendMessageToParent({\r\n name: 'configuratorMessage',\r\n data: {},\r\n correspondenceId: msg.correspondenceId,\r\n });\r\n });\r\n });\r\n });\r\n } else if (messageName == 'getfields') {\r\n let response: any = {};\r\n this.rootConfig.getFields().forEach(f => {\r\n response[f.name] = f.value;\r\n });\r\n Utils.sendMessageToParent({\r\n name: 'configuratorMessage',\r\n data: response,\r\n correspondenceId: msg.correspondenceId,\r\n });\r\n } else if (messageName == 'setconfiguredproduct') {\r\n $scope.$apply(() => {\r\n return this.runConfiguredProduct(rootConfig, data).then(() => {\r\n if ($scope.deferLoadedRule && this.readyToStart) {\r\n this.model = { configuredProduct: data };\r\n this.readyToStart.resolve();\r\n this.readyToStart = null;\r\n }\r\n Utils.sendMessageToParent({\r\n name: 'configuratorMessage',\r\n data: {},\r\n correspondenceId: msg.correspondenceId,\r\n });\r\n });\r\n });\r\n } else if (messageName == 'getconfiguredproduct') {\r\n this.queueRule(() => {\r\n Utils.sendMessageToParent({\r\n name: 'configuratorMessage',\r\n data: this.rootConfig.getConfiguredProduct(),\r\n correspondenceId: msg.correspondenceId,\r\n });\r\n return new KPromise(null) as any;\r\n });\r\n } else if (messageName == 'runaction') {\r\n $scope.$apply(() => {\r\n let action = this.rootConfig.actions.find(a => a.name.isEqual(msg.data));\r\n $scope.runAction(action).then(() => {\r\n Utils.sendMessageToParent({\r\n name: 'configuratorMessage',\r\n data: {},\r\n correspondenceId: msg.correspondenceId,\r\n });\r\n });\r\n });\r\n } else if (messageName == 'saveproductandsubmit') {\r\n $scope.$apply(() => {\r\n // clear out current quote first\r\n quoteService.quote = null;\r\n this.submit(true)\r\n .then(() => {\r\n return this.api.quotes\r\n .submit(this.quoteService.quote, this.$rootScope.contentTracker)\r\n .then(q => {\r\n // clear out the active quote again\r\n quoteService.quote = null;\r\n return q;\r\n });\r\n })\r\n .then(q => {\r\n Utils.sendMessageToParent({\r\n name: 'configuratorMessage',\r\n data: q,\r\n correspondenceId: msg.correspondenceId,\r\n });\r\n });\r\n });\r\n } else if (messageName == 'saveproduct') {\r\n $scope.$apply(() => {\r\n this.submit(true).then(() => {\r\n Utils.sendMessageToParent({\r\n name: 'configuratorMessage',\r\n data: this.quoteService.quote,\r\n correspondenceId: msg.correspondenceId,\r\n });\r\n });\r\n });\r\n } else if (messageName == 'snapshot') {\r\n if ($scope.activeSceneViewer) {\r\n $scope.activeSceneViewer.snapshot(msg.data).then(result => {\r\n if (result) {\r\n Utils.sendMessageToParent({\r\n name: 'configuratorMessage',\r\n data: result,\r\n correspondenceId: msg.correspondenceId,\r\n });\r\n }\r\n });\r\n }\r\n } else if (messageName == 'runsubmitrule') {\r\n $scope.$apply(() => {\r\n this.runSubmitRule().then(() => {\r\n Utils.sendMessageToParent({\r\n name: 'configuratorMessage',\r\n data: {},\r\n correspondenceId: msg.correspondenceId,\r\n });\r\n });\r\n });\r\n } else if (messageName == 'getprice') {\r\n $scope.$apply(() => {\r\n this.runPricing().then(() => {\r\n Utils.sendMessageToParent({\r\n name: 'configuratorMessage',\r\n data: this.rootConfig.priceObject,\r\n correspondenceId: msg.correspondenceId,\r\n });\r\n });\r\n });\r\n } else {\r\n let messageArgs: IConfiguratorMessageRuleArgs = jQuery.extend(\r\n this.getRuleArgs(this.rootConfig),\r\n { message: msg }\r\n );\r\n\r\n if (this.rootConfig.hasRule(eRuleType.message)) {\r\n return this.queueEventRuleType(this.rootConfig, eRuleType.message, messageArgs).then(\r\n () => {\r\n this.$scope.$digest();\r\n }\r\n );\r\n }\r\n }\r\n }\r\n }\r\n };\r\n $window.addEventListener('message', messageHandler);\r\n $window.addEventListener('keydown', $scope.keydown);\r\n\r\n $scope.$on('$destroy', () => {\r\n $window.removeEventListener('message', messageHandler);\r\n $window.removeEventListener('keydown', $scope.keydown);\r\n });\r\n\r\n // $scope.$watchCollection(\"config.actions\", () => {\r\n // $timeout(() => this.resizeActionBar(), 1);\r\n // });\r\n\r\n // this.resizeActionBar = Utils.throttle(() => {\r\n // // $timeout(() => {\r\n // let moreButtonsVisible = false;\r\n // //let $actionBar = $(\".kb-config__action-bar\");\r\n // let $header = $(\".kb-config__header\");\r\n // let $moreButton = $(\".kb-config__more-actions\");\r\n\r\n // // get more button width\r\n // $moreButton.css(\"display\", \"inline-block\");\r\n // let moreButtonWidth = $moreButton.outerWidth();\r\n // $moreButton.css(\"display\", \"\");\r\n\r\n // let available = $header.outerWidth() / 2 - moreButtonWidth; //$actionBar.outerWidth() - moreButtonWidth;\r\n // let taken: number = 0;\r\n // this.$scope.config.actions.forEach(action => {\r\n // if (action.visible) {\r\n // let $action = $(\"#action-\" + action.id);\r\n // let $moreAction = $(\"#action-more-\" + action.id);\r\n // // temporarily set the action to be visible even if it's\r\n // // currently hidden because it's in the more menu\r\n // $action.css(\"display\", \"inline-block\");\r\n // let actionWidth = $action.outerWidth();\r\n // taken += actionWidth;\r\n\r\n // let visibleInMore = (taken > available);\r\n // if (visibleInMore) moreButtonsVisible = true;\r\n\r\n // $action.css(\"display\", visibleInMore ? \"none\" : \"\");\r\n // $moreAction.css(\"display\", visibleInMore ? \"\" : \"none\");\r\n // }\r\n // });\r\n // $moreButton.css(\"display\", moreButtonsVisible ? \"\" : \"none\");\r\n // // });\r\n // }, 100);\r\n\r\n this.runResizeRule = Utils.debounce(() => {\r\n // run the resize rule of the configurator\r\n if (this.$scope.config.getRuleJs(eRuleType.resize) || this.$scope.config.getRuleJs(eRuleType.layout)) {\r\n let args = this.getRuleArgs(this.$scope.config);\r\n this.helper.runRuleTypeAsync(this.$scope.config, eRuleType.resize, args).then(() => {\r\n if (this.$scope.config.hasRule(eRuleType.layout)) {\r\n this.runLayoutRule(this.$scope.config, args).then(() => {\r\n this.$scope.$digest();\r\n });\r\n }\r\n });\r\n }\r\n }, 100);\r\n\r\n $(window).resize(() => {\r\n $timeout(() => {\r\n this.runResizeRule();\r\n //this.resizeActionBar();\r\n this.refreshDrawer();\r\n }, 1);\r\n });\r\n\r\n // get pricing columns if relevant\r\n if (this.hasPricing()) {\r\n this.api.priceColumns.getPriceColumnsForUser().then(r => {\r\n this.$scope.priceColumns = r;\r\n this.$scope.priceColumnDb = {};\r\n this.$scope.priceColumns.forEach(pc => (this.$scope.priceColumnDb[pc.name] = pc));\r\n this.$scope.pricePrecision = this.$scope.priceColumns.find(\r\n pc => pc.id == 14 /* <-- ExtNetPrice --> */\r\n ).precision;\r\n });\r\n }\r\n\r\n this.drawerService.pageTitle = this.rootConfig.name;\r\n this.drawerService.pageType = loc.configurator;\r\n this.drawerService.pageIcon = icons.configurator;\r\n this.drawerService.showHelp = false;\r\n\r\n if (this.$scope.isTest) {\r\n if (rootConfig.builds.length) {\r\n let drawers: IDrawer[] = [];\r\n rootConfig.builds.forEach(b => {\r\n drawers.push({\r\n icon: icons.gear,\r\n label: b.name,\r\n command: () => {\r\n $scope.testBuild(b);\r\n },\r\n });\r\n });\r\n drawerService.addDrawer(icons.test, loc.testbuild, () => {}, true, drawers);\r\n }\r\n drawerService.addDrawer(icons.test, loc.testpricing, () => {\r\n let pricingArgs: IPricingRuleArgs = jQuery.extend(this.getRuleArgs(this.rootConfig), {\r\n priceObject: {\r\n items: [],\r\n fields: {},\r\n } as IPriceObject,\r\n quoteCreator: this.$rootScope.user,\r\n quoteOwner: this.$rootScope.user,\r\n });\r\n return this.helper.runRuleTypeAsync(this.rootConfig, eRuleType.pricing, pricingArgs);\r\n });\r\n drawerService.addDrawer(icons.name, loc.runnamingrule, () => {\r\n this.helper.runRuleTypeAsync(this.rootConfig, eRuleType.naming);\r\n });\r\n }\r\n\r\n // this.drawerViewer = drawerService.addDrawer(icons.threeD, loc.threedview, () => {\r\n // this.$scope.togglePages(false);\r\n // });\r\n // this.drawerViewer.classes = \"visible-xs\";\r\n // this.drawerOptions = drawerService.addDrawer(icons.group, loc.options, () => {\r\n // this.$scope.togglePages(true);\r\n // });\r\n // this.drawerOptions.classes = \"visible-xs\";\r\n // this.drawerPricing = drawerService.addDrawer(icons.column, loc.details, () => {\r\n // this.$scope.showPricing();\r\n // });\r\n // this.drawerPricing.classes = \"visible-xs\";\r\n\r\n this.drawerSubmitAndStay = drawerService.addDrawer(icons.save, $scope.getSubmitAndStayButtonText(), () => {\r\n this.submit(true);\r\n });\r\n\r\n this.drawerSubmit = drawerService.addDrawer(icons.quote, $scope.getSubmitButtonText(), () => {\r\n this.submit();\r\n });\r\n\r\n // this.drawerGenerateQrCode = drawerService.addDrawer(icons.add, $scope.getGenerateQrCodeText(), () => {\r\n // this.qrCodeModal();\r\n // });\r\n\r\n if ($scope.isEdit) {\r\n if (this.$rootScope.isSfdcCpq) {\r\n this.drawerSubmit.icon = icons.save;\r\n } else {\r\n this.api.quotes.getById(this.model.idQuote).then(quote => {\r\n $scope.parentQuote = quote;\r\n if (this.$rootScope.isSfdc && !this.$rootScope.isSfdcCpq) {\r\n quoteService.quote = quote;\r\n }\r\n if (\r\n (!quote.idWorkflow && quote.createdBy == this.$rootScope.user.id) ||\r\n quote.allowedActions.some(a => a.type == eWorkflowAction.modifyProducts)\r\n ) {\r\n let builds = quote.allowedActions\r\n .filter(a => a.type == eWorkflowAction.buildQuoteProduct)\r\n .filter(a => rootConfig.builds.find(b => b.idBuildType == a.buildType.id) != null);\r\n if (builds.length) {\r\n let drawers: IDrawer[] = [];\r\n builds.forEach(action => {\r\n drawers.push({\r\n icon: icons.gear,\r\n label: action.buildType.name,\r\n command: () => {\r\n this.submit().then(() => {\r\n return this.api.quotes.buildQuoteProduct(\r\n quote.id,\r\n this.model.id,\r\n action.buildType.id\r\n );\r\n });\r\n },\r\n });\r\n });\r\n drawerService.addDrawer(icons.build, 'Build', () => {}, true, drawers);\r\n }\r\n } else {\r\n drawerService.drawers.remove(this.drawerSubmit);\r\n drawerService.drawers.remove(this.drawerSubmitAndStay);\r\n $scope.isReadOnly = true;\r\n drawerService.addDrawer(icons.cancel, loc.back, () => {\r\n this.$state.go('kb.quoteEdit', { id: this.model.idQuote });\r\n });\r\n }\r\n });\r\n }\r\n\r\n //after running the configured product, nested configs could have been added to nested\r\n //sets. We need to set the $nestedSetElement on those configs\r\n this.setAllNestedSetElements(rootConfig);\r\n }\r\n\r\n //this.runContinuousAsyncRule();\r\n\r\n // select the first page after defining the pagechanged handler\r\n this.selectNode(rootConfig.pages.find(p => p.visible == true));\r\n this.$scope.togglePages(true);\r\n\r\n this.readyToStart = $q.defer();\r\n\r\n this.startConfigurator();\r\n });\r\n }\r\n\r\n private runAsyncRule: boolean = true;\r\n\r\n private requestId: string;\r\n private model: IQuoteProduct;\r\n private readyToStart: ng.IDeferred;\r\n public helper: ConfiguratorHelper;\r\n public rootConfig: Configurator;\r\n private activeRule: ng.IPromise;\r\n private validationPromptDisplayed: boolean;\r\n\r\n // a cache of scene sessions in case the configurator loads the same scene multiple times\r\n public sceneDb: { [id: string]: IScene } = {};\r\n public productDb: { [id: number]: IProduct } = {};\r\n public translationDb: { [idProduct: number]: { [id: string]: ITranslationPackage } } = {};\r\n public sceneViewerDb: { [id: number]: SceneViewer } = {}; // holds a map of sceneViewer's to the scene id\r\n public loading: boolean = true; // whether the configurator is currently loading\r\n public configSession: IConfiguratorSession;\r\n public lastPricingPromise: ng.IPromise;\r\n public lastViewerPromise: ng.IPromise;\r\n public nextViewerPromise: ng.IPromise;\r\n public sfdcCpqPayload: ISfdcCpqPayload;\r\n public drawerSubmit: IDrawer;\r\n public drawerSubmitAndStay: IDrawer;\r\n public drawerGenerateQrCode: IDrawer;\r\n public runResizeRule: () => void;\r\n public configuratorLoadedDeferred: angular.IDeferred;\r\n\r\n public selectNode(tab: Page | Configurator) {\r\n this.$scope.selected.node = tab;\r\n }\r\n\r\n public navigateToElement(o: UiObject) {\r\n let animateTo: UiObject = null;\r\n let waitFor: number = 0;\r\n let waitPromise: PromiseLike = new KPromise(null);\r\n\r\n if (o.visible) {\r\n if (o instanceof Page) {\r\n this.selectNode(o);\r\n } else if (o instanceof Configurator) {\r\n if (o.$parent instanceof NestedSet) {\r\n let ancestorNestedSets = [o.$parent];\r\n let p = o.$parent;\r\n while (p) {\r\n ancestorNestedSets.push(p);\r\n if (p.$parentConfigurator.$parent instanceof NestedSet) {\r\n p = p.$parentConfigurator.$parent;\r\n } else {\r\n p = null;\r\n }\r\n }\r\n\r\n let page = ancestorNestedSets.last().findAncestor(kbo => kbo instanceof Page) as Page;\r\n if (page && page.visible) {\r\n this.selectNode(page);\r\n animateTo = o;\r\n\r\n for (let i = ancestorNestedSets.length - 1; i >= 0; i--) {\r\n let nestedSet = ancestorNestedSets[i];\r\n\r\n if (nestedSet.display == eNestedSetDisplay.accordion) {\r\n waitPromise = waitPromise.then(() => {\r\n return this.$timeout(() => {\r\n if (!o['expanded']) waitFor = 350;\r\n o['expanded'] = true;\r\n return this.$timeout(); //we also need to wait for other expanders in the accordion to finish so we return another timeout\r\n });\r\n });\r\n } else if (nestedSet.display == eNestedSetDisplay.tabControl) {\r\n nestedSet['$selectedTab'] = o.name;\r\n animateTo = nestedSet;\r\n }\r\n }\r\n }\r\n } else {\r\n this.selectNode(o.pages.find(p => p.visible));\r\n }\r\n } else {\r\n let page = o.findAncestor(kbo => kbo instanceof Page) as Page;\r\n if (page && page.visible) {\r\n this.selectNode(page);\r\n animateTo = o;\r\n }\r\n }\r\n if (animateTo) {\r\n waitPromise.then(() => {\r\n this.$timeout(() => {\r\n let $uiObject = jQuery('.' + animateTo.$domId + ':visible');\r\n if ($uiObject.length) {\r\n Utils.scrollIntoView({\r\n elem: $uiObject[0],\r\n mode: eScrollMode.middleIfNecessary,\r\n animate: true,\r\n });\r\n }\r\n }, waitFor);\r\n });\r\n }\r\n }\r\n }\r\n\r\n public setAllNestedSetElements(config: Configurator) {\r\n //after running the configured product, nested configs could have been added to nested\r\n //sets. We need to set the $nestedSetElement on those configs\r\n for (let nested of config.getAllConfigurators()) {\r\n this.handleNewConfigInNestedSet(nested, nested.$parent as Configurator | NestedSet | Page, false);\r\n }\r\n }\r\n\r\n public refreshDrawer() {\r\n if (this.$scope.isEmbed) {\r\n // only show the submit button if the configurator says it should be shown\r\n if (this.drawerSubmit)\r\n this.drawerSubmit.visible = this.drawerSubmitAndStay.visible = this.$scope.config.showSubmitButton;\r\n }\r\n if (this.$rootScope.isSfdcCpq) {\r\n if (this.drawerSubmit) {\r\n let isValid = this.$scope.config.isValid();\r\n this.drawerSubmit.disabled = !isValid;\r\n // if (!isValid) {\r\n // this.drawerService.validationMessage = loc.validation_sfdc_correcterrors;\r\n // }\r\n }\r\n if (this.drawerSubmitAndStay) {\r\n this.drawerSubmitAndStay.visible = false;\r\n }\r\n }\r\n\r\n // if (this.drawerPricing) {\r\n // this.drawerPricing.visible = (this.$rootScope.user && this.$rootScope.user.canViewPrices && this.$scope.config.showPrice);\r\n // }\r\n // let viewerExists = (this.$scope.viewerMode != eViewerMode.none);\r\n // if (this.drawerViewer) {\r\n // this.drawerViewer.visible = viewerExists;\r\n // this.drawerViewer.selected = !this.$scope.showPages;\r\n // }\r\n // if (this.drawerOptions) {\r\n // this.drawerOptions.visible = viewerExists;\r\n // this.drawerOptions.selected = this.$scope.showPages;\r\n // }\r\n }\r\n\r\n public loadSfdcCpqPayload(): ng.IPromise {\r\n if (this.$rootScope.isSfdcCpq) {\r\n return this.sfdcService.getPayloadFromSfdcCpq().then(payload => {\r\n this.sfdcCpqPayload = payload;\r\n this.$scope.isEdit = this.sfdcCpqPayload.quoteProductId != null;\r\n this.$scope.isNew = !this.$scope.isEdit;\r\n this.$scope.sfdcHasCurrency = false;\r\n if (payload.data.quote.CurrencyIsoCode) {\r\n this.$scope.sfdcCurrency = payload.data.quote.CurrencyIsoCode;\r\n this.$scope.sfdcHasCurrency = true;\r\n }\r\n });\r\n } else {\r\n return this.$q.when(null);\r\n }\r\n }\r\n\r\n public loadModel(): ng.IPromise {\r\n if (this.$scope.isEdit) {\r\n let quoteProductId = this.$rootScope.isSfdcCpq ? this.sfdcCpqPayload.quoteProductId : this.$stateParams.id;\r\n return this.api.quoteProducts.getById(quoteProductId, this.$rootScope.contentTracker).then(r => {\r\n this.model = r;\r\n });\r\n } else {\r\n this.model = {};\r\n return this.$q.when(null);\r\n }\r\n }\r\n\r\n /**\r\n * depending on the context, we need to figure out the product id for the configurator\r\n */\r\n public getProductId(): number {\r\n if (this.$rootScope.isSfdcCpq) {\r\n return this.$scope.isEdit ? this.model.idProduct : this.sfdcCpqPayload.productId;\r\n } else {\r\n return this.$scope.isEdit ? this.model.idProduct : this.$stateParams.id;\r\n }\r\n }\r\n\r\n protected addTranslationsForEntity(entity: {\r\n id?: number;\r\n translations?: IProductTranslation[] | ISceneTranslation[];\r\n }) {\r\n var trans = entity.translations.first();\r\n if (trans) {\r\n var entry = this.translationDb[entity.id];\r\n if (!entry) entry = this.translationDb[entity.id] = {};\r\n Object.keys(trans.data.objects).forEach(key => {\r\n entry[key] = trans.data.objects[key];\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * This controller is used for both full configurators and scene configurators.\r\n * We load the configurator differently based on the situation\r\n */\r\n public getConfigurator(): ng.IPromise {\r\n let configuratorPromise: ng.IPromise;\r\n if (this.$scope.isScene) {\r\n // when we are running a scene configurator, the scene is embedded into the html\r\n let session = (window as any).serverVm.session as IConfiguratorSession;\r\n let scene = session.scenes.first();\r\n this.sceneDb[scene.id] = scene;\r\n this.configSession = { idScene: scene.id, scenes: [scene] };\r\n this.addTranslationsForEntity(scene);\r\n this.loadLayout(scene.configurator, session.layout);\r\n this.helper.loadTables(session.tables);\r\n let configurator = new Configurator(new KbObjectManager(), scene.configurator);\r\n configurator.$running = true;\r\n configuratorPromise = new KPromise(configurator) as any as ng.IPromise;\r\n } else {\r\n // it's a normal configurator\r\n configuratorPromise = this.authService.authPromise\r\n .then(() => this.loadSfdcCpqPayload())\r\n .then(() => this.loadModel())\r\n .then(() => {\r\n let id = this.getProductId();\r\n // if we are in test mode, we get the entire product with server rules\r\n // like pricing rule(so they can be debugged on the client)\r\n return this.api.products\r\n .run(\r\n id,\r\n this.$scope.isTest,\r\n this.$rootScope.environment != eEnvironment.dev, //whether to get the configSession pre-compressed\r\n this.$rootScope.contentTracker\r\n )\r\n .then(\r\n session => {\r\n //special handling for nested parent\r\n id = session.idProduct;\r\n this.configSession = session;\r\n // load the productDb\r\n session.products.forEach(p => (this.productDb[p.id] = p));\r\n // load the scene session db\r\n session.scenes.forEach(s => (this.sceneDb[s.id] = s));\r\n // load the translation db\r\n session.products.forEach(p => {\r\n this.addTranslationsForEntity(p);\r\n });\r\n session.scenes.forEach(s => {\r\n this.addTranslationsForEntity(s);\r\n });\r\n\r\n return this.fillSourcedTables(session).then(() => {\r\n this.helper.loadTables(session.tables);\r\n\r\n // fill in the pages / nested configurators db\r\n this.$scope.userCanAddToDb = {};\r\n session.products.forEach(product => {\r\n this.$scope.userCanAddToDb[product.id] = {};\r\n if (product.configurator.referencedConfigurators) {\r\n product.configurator.referencedConfigurators.forEach(rc => {\r\n if (rc.userCanAddTo) {\r\n rc.userCanAddTo.forEach(pageId => {\r\n let entry =\r\n this.$scope.userCanAddToDb[product.id][pageId] ||\r\n (this.$scope.userCanAddToDb[product.id][pageId] = []);\r\n entry.push({\r\n id: rc.idProduct,\r\n name: this.productDb[rc.idProduct].name,\r\n });\r\n });\r\n }\r\n });\r\n }\r\n });\r\n\r\n this.$scope.entity = this.productDb[id];\r\n let configurator = new Configurator(\r\n new KbObjectManager(),\r\n this.productDb[id].configurator\r\n );\r\n configurator.$running = true;\r\n this.$scope.showMove = this.$scope.showMove || configurator.showMoveAnimation;\r\n\r\n if (this.$scope.embedFields) {\r\n configurator.setFields(this.$scope.embedFields);\r\n }\r\n\r\n if (this.$scope.isEdit) {\r\n configurator.runConfiguredProduct(this.model.configuredProduct, this.productDb);\r\n configurator.sku = this.model.sku;\r\n configurator.name = this.model.name;\r\n configurator.description = this.model.description;\r\n configurator.shortDescription = this.model.shortDescription;\r\n }\r\n\r\n this.loadLayout(configurator, session.layout);\r\n\r\n return configurator;\r\n });\r\n },\r\n err => {\r\n this.dialogService.alert({\r\n type: eAlertType.error,\r\n msg: 'Product not found',\r\n persist: true,\r\n });\r\n this.$state.go('kb.products');\r\n this.configuratorLoadedDeferred.reject('Product not found');\r\n return null;\r\n }\r\n );\r\n });\r\n }\r\n return configuratorPromise;\r\n }\r\n\r\n protected loadLayout(rootConfig: Configurator | IConfigurator, layout: ILayout) {\r\n this.$scope.layoutConfig = new LayoutConfig(new KbObjectManager(), layout.layoutConfig);\r\n\r\n // load the layout settings into the layout\r\n if (rootConfig.layoutSettings) {\r\n rootConfig.layoutSettings.forEach(ls => {\r\n let field = this.$scope.layoutConfig.$manager.getByIdOrName(ls.id || ls.name, false);\r\n if (field) field.value = ls.value;\r\n });\r\n }\r\n\r\n //layout settings from the embed take precedence over those in the configurator properties screen, so we set them after\r\n if (this.$scope.embedLayoutSettings) {\r\n for (let lsname in this.$scope.embedLayoutSettings) {\r\n let field = this.$scope.layoutConfig.$manager.getByIdOrName(lsname, false);\r\n if (field) field.value = this.$scope.embedLayoutSettings[lsname];\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * starts a configurator by loading any tables it references and running the rules once\r\n * @param config\r\n */\r\n public startConfigurator(): ng.IPromise {\r\n this.readyToStart = this.$q.defer();\r\n if (this.$scope.deferLoadedRule) {\r\n Utils.sendMessageToParent({\r\n name: 'readyToLoadConfiguredProduct',\r\n data: {\r\n requestId: this.requestId,\r\n },\r\n });\r\n } else {\r\n this.readyToStart.resolve();\r\n }\r\n return this.readyToStart.promise.then(() =>\r\n this.queueRule(() =>\r\n this.runLayoutRule(this.rootConfig, this.getRuleArgs(this.rootConfig))\r\n .then(() =>\r\n //start with layout rule so we don't get FOUC\r\n this.nestedRunBottomsUp(this.rootConfig, c =>\r\n this.runRuleCycleUnit(c, null).then(() => {\r\n // run the loaded rule\r\n let args = this.getLoadedRuleArgs(c);\r\n let origNumberOfNesteds = c.getNestedConfigurators().length;\r\n return this.helper.runRuleTypeAsync(c, eRuleType.resize, args).then(() => {\r\n return (\r\n this.runLoadedRule(c, args)\r\n // if the loaded rule changed field values or added nested\r\n // configs we need to run the rule cycle again\r\n .then(() => {\r\n if (\r\n c.$fieldsDirty ||\r\n origNumberOfNesteds != c.getNestedConfigurators().length\r\n ) {\r\n return this.runRuleCycleUnit(c, null);\r\n }\r\n })\r\n );\r\n });\r\n })\r\n )\r\n )\r\n .then(() => {\r\n this.loading = false;\r\n return this.oncePerCycleRule();\r\n })\r\n .then(() => {\r\n this.configuratorLoadedDeferred.resolve();\r\n Utils.sendMessageToParent({\r\n name: 'configuratorLoaded',\r\n data: {\r\n requestId: this.requestId,\r\n },\r\n });\r\n })\r\n )\r\n );\r\n }\r\n\r\n public saveToQuote(): ng.IPromise {\r\n //!!!Should only be called by \"submit\". Everything else should call submit() which calls this\r\n if (this.$rootScope.isSfdcCpq) {\r\n // if steelbrick, then add the product to a blank quote and submit it\r\n let quote = this.quoteService.getNewQuote();\r\n quote.externalId = this.sfdcCpqPayload.data.quote.Id;\r\n // name the quote the same as the sfdc cpq quote for tracking\r\n // in version 28.0.1 of steelbrick they took away the record property\r\n quote.name = (this.sfdcCpqPayload.data.quote as any).record\r\n ? (this.sfdcCpqPayload.data.quote as any).record.Name\r\n : this.sfdcCpqPayload.data.quote.Name;\r\n\r\n quote.products = [\r\n {\r\n idProduct: this.$scope.entity.id,\r\n qty: 1,\r\n configuredProduct: this.rootConfig.getConfiguredProduct(),\r\n },\r\n ];\r\n return this.api.quotes.save(quote, this.$rootScope.contentTracker).then(q => {\r\n // add the quoteproduct id to the payload so it can be saved in sfdc cpq\r\n this.sfdcCpqPayload.quoteProductId = q.products[0].id;\r\n return q.products[0];\r\n });\r\n } else if (this.$scope.isNew) {\r\n return this.quoteService\r\n .addProduct({\r\n idProduct: this.$scope.entity.id,\r\n qty: 1,\r\n configuredProduct: this.rootConfig.getConfiguredProduct(),\r\n addLocally: true,\r\n silent: this.$scope.isEmbed, // don't show confirmation dialog if we are in an embed\r\n currency: this.$scope.getCurrency(),\r\n })\r\n .then(r => {\r\n return r;\r\n });\r\n } else {\r\n this.model.configuredProduct = this.rootConfig.getConfiguredProduct();\r\n return this.api.quotes\r\n .editQuoteProduct(this.model.idQuote, this.model, this.$rootScope.contentTracker)\r\n .then(r => {\r\n const result = this.quoteService.getLatestQuoteProduct(r);\r\n return result;\r\n });\r\n }\r\n }\r\n\r\n private setSubmitButtonDisabled(disabled: boolean) {\r\n this.drawerSubmitAndStay.disabled = this.drawerSubmit.disabled = disabled;\r\n }\r\n\r\n public submit(stayOnPage: boolean = false): ng.IPromise {\r\n this.setSubmitButtonDisabled(true);\r\n let deferred = this.$q.defer();\r\n let promise = deferred.promise;\r\n this.validationPromptDisplayed = false;\r\n\r\n /* \r\n Process validation before AND after running the submit rule.\r\n We run it before because in some scenarios people are adding nested configurators in the submit rule,\r\n and if we're not valid already, then we'd rather not add them.\r\n We run it after too because perhaps the submit rule changed something that makes it invalid.\r\n */\r\n this.shouldSubmit().then(should => {\r\n if (should) {\r\n this.runSubmitRule().then(() => {\r\n this.shouldSubmit().then(should => {\r\n if (should) {\r\n this.saveToQuote().then(r => {\r\n deferred.resolve(r);\r\n });\r\n } else {\r\n deferred.reject();\r\n }\r\n });\r\n });\r\n } else {\r\n deferred.reject();\r\n }\r\n });\r\n\r\n return promise\r\n .then(\r\n data => {\r\n this.telemetryService.trackEvent('Configurator Submit');\r\n if (this.$rootScope.isSfdcCpq) {\r\n this.sfdcService.saveToSfdcCpq(this.sfdcCpqPayload, data.priceObject);\r\n } else if (this.$scope.isNew && !this.$scope.isEmbed) {\r\n if (stayOnPage) {\r\n this.$state.go('kb.configuredProduct', { id: data.id });\r\n } else {\r\n this.quoteService.goToQuote();\r\n }\r\n } else if (this.$scope.isEdit) {\r\n this.$scope.$broadcast('saveSuccess', data);\r\n if (!stayOnPage) this.$state.go('kb.quoteEdit', { id: this.model.idQuote });\r\n }\r\n },\r\n reason => {\r\n this.telemetryService.trackEvent('Configurator Submit Rejected');\r\n this.setSubmitButtonDisabled(false);\r\n return this.$q.reject(reason);\r\n }\r\n )\r\n .finally(() => {\r\n if (stayOnPage)\r\n this.setSubmitButtonDisabled(false);\r\n });\r\n }\r\n\r\n public qrCodeModal() {\r\n const dialogScope: IGenerateQrCodeScope = this.$rootScope.$new();\r\n dialogScope.autoStartAr = false;\r\n let url = window.location.href;\r\n if (url.includes('ar=true')) {\r\n dialogScope.autoStartAr = true;\r\n }\r\n dialogScope.updateQrCode = newVal => {\r\n if (newVal !== dialogScope.autoStartAr) {\r\n dialogScope.autoStartAr = newVal;\r\n }\r\n };\r\n const canvas = document.createElement('canvas');\r\n QRCode.toCanvas(canvas, url, { width: 150 }, function (error) {\r\n if (error) console.error(error);\r\n });\r\n dialogScope.QrCode = canvas;\r\n\r\n this.dialogService.dialog({\r\n template: Dirs.view('dialog-create-qr-code', eBundle.app),\r\n scope: dialogScope,\r\n buttons: [new InputDialogButton(loc.cancel, icons.cancel, args => {})],\r\n });\r\n\r\n dialogScope.$watch(\r\n 'autoStartAr',\r\n function (newVal) {\r\n if (newVal === true) {\r\n if (url.includes('ar=true') === false) {\r\n url = url + '?ar=true';\r\n }\r\n\r\n window.history.pushState({}, null, url);\r\n QRCode.toCanvas(canvas, url, { width: 150 }, function (error) {\r\n if (error) console.error(error);\r\n });\r\n } else {\r\n if (url.includes('ar=true') === true) {\r\n url = url.replace('ar=true', '');\r\n if (url.charAt(url.length - 1) === '?') {\r\n url = url.slice(0, -1);\r\n }\r\n }\r\n\r\n window.history.pushState({}, null, url);\r\n QRCode.toCanvas(canvas, url, { width: 150 }, function (error) {\r\n if (error) console.error(error);\r\n });\r\n }\r\n const panel: HTMLElement = document.getElementById('qrCodeCanvas');\r\n if (panel instanceof HTMLCanvasElement) {\r\n const context = panel.getContext('2d');\r\n context.clearRect(0, 0, canvas.width, canvas.height);\r\n context.drawImage(canvas, 0, 0);\r\n //panel.append(canvas);\r\n }\r\n //dialogScope.QrCode = canvas;\r\n },\r\n true\r\n );\r\n\r\n setTimeout(() => {\r\n const panel: HTMLElement = document.getElementById('qrCodeCanvas');\r\n QRCode.toCanvas(panel, url, { width: 150 }, function (error) {\r\n if (error) console.error(error);\r\n });\r\n panel.append(canvas);\r\n }, 1000);\r\n }\r\n\r\n public enterArModal() {\r\n const dialogScope = this.$rootScope.$new();\r\n const enterArButton = new InputDialogButton('Enter AR', icons.change, args => {\r\n if (this.$scope.activeSceneViewer) {\r\n this.$scope.activeSceneViewer.$scope.toggleAr();\r\n }\r\n });\r\n this.dialogService.dialog({\r\n scope: dialogScope,\r\n buttons: [enterArButton, new InputDialogButton(loc.cancel, icons.cancel, args => {})],\r\n });\r\n }\r\n\r\n public shouldSubmit(): ng.IPromise {\r\n let deferred = this.$q.defer();\r\n\r\n if (this.rootConfig.isValid()) {\r\n deferred.resolve(true);\r\n } else {\r\n //it's not valid\r\n if (this.rootConfig.allowSaveWithErrors) {\r\n if (!this.validationPromptDisplayed) {\r\n this.validationPromptDisplayed = true;\r\n this.dialogService.dialog({\r\n content: loc.msg_savetoquoteerrors,\r\n buttons: [\r\n new DialogButton(loc.save, icons.success, args => {\r\n deferred.resolve(true);\r\n }),\r\n new DialogButton(loc.keepworking, icons.cancel, args => {\r\n deferred.resolve(false);\r\n }),\r\n ],\r\n });\r\n } else {\r\n deferred.resolve(true);\r\n }\r\n } else {\r\n this.dialogService.alert({\r\n msg: loc.msg_fixerrorsbeforesave,\r\n persist: false,\r\n type: eAlertType.error,\r\n });\r\n deferred.resolve(false);\r\n }\r\n }\r\n\r\n return deferred.promise;\r\n }\r\n\r\n public runConfiguredProduct(configurator: Configurator, configProd: IConfiguredProduct) {\r\n return this.queueRule(() => {\r\n configurator.runConfiguredProduct(configProd, this.productDb);\r\n this.setAllNestedSetElements(configurator);\r\n return this.nestedRunBottomsUp(configurator, c => this.runRuleCycleUnit(c, null)).then(() =>\r\n this.oncePerCycleRule()\r\n );\r\n });\r\n }\r\n\r\n public addNestedConfig(\r\n idNested: number,\r\n parent: Page | Configurator | NestedSet,\r\n addedByUser: boolean,\r\n name: string,\r\n fields?: {}\r\n ): ng.IPromise {\r\n let product = this.productDb[idNested];\r\n\r\n // if a configurator with the given name already exists, then we do nothing\r\n let nested = parent.configurators.find(c => c.name.isEqual(name));\r\n if (!nested) {\r\n nested = new Configurator(new KbObjectManager(), product.configurator);\r\n nested.$running = true;\r\n if (name) nested.name = name;\r\n parent.$expanded = true;\r\n parent.configurators.push(nested);\r\n parent.$manager.addKbObject(nested, parent);\r\n if (addedByUser) nested.addedByUser = this.$rootScope.user.id;\r\n\r\n if (fields) {\r\n nested.setFields(fields);\r\n }\r\n\r\n let parentConfig = parent instanceof Configurator ? (parent as Configurator) : parent.$parentConfigurator;\r\n this.handleNewConfigInNestedSet(nested, parent);\r\n\r\n if (this.sceneDb[nested.idScene] && this.sceneDb[nested.idScene].external) {\r\n nested.nestedPath = nested.idScene;\r\n } else {\r\n nested.nestedPath = this.getConfiguratorUniqueKey(nested);\r\n }\r\n\r\n // run the added rule on the nested configurator\r\n return this.runNestedRuleType(parentConfig, nested, eRuleType.configuratorAdded)\r\n .then(() => this.runRuleCycleUnit(nested, null, false)) // don't bubble here\r\n .then(() => nested);\r\n } else if (fields) {\r\n nested.setFields(fields); //no need to run\r\n if (nested.$fieldsDirty) {\r\n return this.runRuleCycleUnit(nested, null, false).then(() => nested);\r\n } else {\r\n return new KPromise(nested) as any;\r\n }\r\n } else {\r\n return new KPromise(nested) as any;\r\n }\r\n }\r\n\r\n public getConfiguratorUniqueKey(config: Configurator) {\r\n let looping = true;\r\n do {\r\n let nestedSettings = undefined;\r\n if (config.$parentConfigurator) {\r\n nestedSettings = config.$parentConfigurator.referencedConfigurators.find(rc => rc.name === config.name);\r\n }\r\n if (nestedSettings && nestedSettings.nestScene) {\r\n config = config.$parentConfigurator;\r\n } else {\r\n looping = false;\r\n }\r\n } while (looping);\r\n\r\n if (config.$parentConfigurator) {\r\n return config.$parentConfigurator.name + '/' + config.name;\r\n } else {\r\n return config.name;\r\n }\r\n }\r\n\r\n public copyNestedConfig(\r\n sourceConfig: Configurator,\r\n appendTo: Page | Configurator | NestedSet,\r\n addedByUser: boolean,\r\n name?: string\r\n ) {\r\n let product = this.productDb[sourceConfig.idProduct];\r\n\r\n let target = new Configurator(new KbObjectManager(), product.configurator);\r\n target.$running = true;\r\n target.runConfiguredProduct(sourceConfig.getConfiguredProduct(), this.productDb);\r\n target.name = name || product.configurator.name; // get default name\r\n\r\n appendTo.$expanded = true;\r\n appendTo.configurators.push(target);\r\n appendTo.$manager.addKbObject(target, appendTo);\r\n if (addedByUser) target.addedByUser = this.$rootScope.user.id;\r\n this.handleNewConfigInNestedSet(target, appendTo);\r\n\r\n // run the added rule on the nested configurator\r\n return this.runNestedRuleType(sourceConfig.$parentConfigurator, target, eRuleType.configuratorCopied)\r\n .then(() => this.nestedRunBottomsUp(target, c => this.runRuleCycleUnit(c, null)))\r\n .then(() => this.oncePerCycleRule())\r\n .then(() => target);\r\n }\r\n\r\n protected handleNewConfigInNestedSet(\r\n nested: Configurator,\r\n parent: Page | Configurator | NestedSet,\r\n navigateTo: boolean = true\r\n ) {\r\n //we need to save a handle to the element chosen to represent the nested set so we can access it in our angular view\r\n if (parent && parent instanceof NestedSet) {\r\n //get the referenced configurator\r\n let refConfig = parent.$parentConfigurator.referencedConfigurators.find(\r\n rc => rc.idProduct == nested.idProduct\r\n );\r\n nested.$nestedSetElement = nested.$manager.get(refConfig.element);\r\n if (parent.visible && parent.autoNavigateToElement && navigateTo) {\r\n this.$timeout(() => {\r\n this.navigateToElement(nested);\r\n });\r\n }\r\n }\r\n }\r\n\r\n public removeNestedConfig(nested): ng.IPromise {\r\n return new KPromise(nested).then(() => {\r\n if (nested) {\r\n // might be a page or configurator passed in. If it's a page,\r\n // it's the page's parent configurator that needs to be deleted\r\n if (nested instanceof Page || nested instanceof NestedSet)\r\n nested = nested.$parentConfigurator as Configurator;\r\n\r\n // we need a new selection if we are deleting the page we're on\r\n if (this.$scope.selected.page) {\r\n if (this.$scope.selected.page.findAncestor(a => a == nested)) {\r\n if (nested.$parent instanceof Page) {\r\n this.selectNode(nested.$parent as Page);\r\n } else {\r\n this.selectNode((nested.$parent as Configurator).pages.find(p => p.visible));\r\n }\r\n }\r\n }\r\n\r\n nested.$parent.$manager.removeKbObject(nested);\r\n (nested.$parent as Page | Configurator | NestedSet).configurators.remove(nested as Configurator);\r\n\r\n let parentConfig =\r\n nested.$parent instanceof Configurator\r\n ? (nested.$parent as Configurator)\r\n : nested.$parent.$parentConfigurator;\r\n\r\n // run the removed rule on the nested configurator\r\n return this.runNestedRuleType(parentConfig, nested as Configurator, eRuleType.configuratorRemoved);\r\n }\r\n }) as any;\r\n }\r\n\r\n public setNumberOfNestedConfigs(\r\n productId: number,\r\n parent: Page | Configurator | NestedSet,\r\n num: number\r\n ): ng.IPromise {\r\n let product = this.productDb[productId];\r\n let configs = parent.configurators.filter(c => c.idProduct == productId);\r\n let promises: ng.IPromise[] = [];\r\n let configsChanged: boolean = false;\r\n if (configs.length < num) {\r\n // need to add\r\n for (let i = configs.length; i < num; i++) {\r\n configsChanged = true;\r\n promises.push(this.addNestedConfig(productId, parent, false, null));\r\n }\r\n } else if (configs.length > num) {\r\n // need to remove\r\n for (let i = configs.length - 1; i >= num; i--) {\r\n configsChanged = true;\r\n promises.push(this.removeNestedConfig(configs[i]));\r\n }\r\n }\r\n let prom: ng.IPromise = this.$q.all(promises);\r\n if (configsChanged) {\r\n let parentConfig = parent instanceof Configurator ? (parent as Configurator) : parent.$parentConfigurator;\r\n prom = prom.then(() => this.runRuleCycleUnit(parentConfig, null));\r\n }\r\n return prom;\r\n }\r\n\r\n protected getChildrenForNode(tabNode: ITabNode): ITabNode[] {\r\n let nodes: ITabNode[] = [];\r\n tabNode.node.pages.forEach(p => {\r\n if (p.visible && !this.$scope.selected.isSingleNode(p.$parentConfigurator)) {\r\n let child = { id: p.id, level: tabNode.level + 1, node: p };\r\n nodes.push(child);\r\n nodes.pushArray(this.getChildrenForNode(child));\r\n }\r\n });\r\n tabNode.node.configurators.forEach(c => {\r\n let child = { id: c.id, level: tabNode.level + 1, node: c };\r\n nodes.push(child);\r\n nodes.pushArray(this.getChildrenForNode(child));\r\n });\r\n return nodes;\r\n }\r\n\r\n public calculateNodes() {\r\n let rootNode: ITabNode = { id: this.rootConfig.id, level: -1, node: this.rootConfig };\r\n this.$scope.nodes = [];\r\n this.$scope.nodes.pushArray(this.getChildrenForNode(rootNode));\r\n\r\n this.$scope.nextNode = this.getNextNode(this.$scope.selected.page, false);\r\n this.$scope.backNode = this.getBackNode(this.$scope.selected.node);\r\n }\r\n\r\n public getNextNode(node: Page | Configurator, skipChildren: boolean) {\r\n let next: Page | Configurator;\r\n if (node) {\r\n let parent = node.$parent as Page | Configurator;\r\n if (!skipChildren) {\r\n // first find if there is a nested page\r\n next = node.pages.find(p => p.visible);\r\n // then check nested configurators\r\n if (!next) next = node.configurators.find(c => c.pages.some(p => p.visible));\r\n }\r\n // get next page or configurator with the same parent\r\n if (!next && parent) {\r\n if (node instanceof Page) {\r\n next = parent.pages.next(node, p => p.visible);\r\n }\r\n if (!next) next = parent.configurators.next(node as Configurator, c => c.pages.some(p => p.visible));\r\n }\r\n\r\n if (!next && parent) next = this.getNextNode(parent, true);\r\n }\r\n return next;\r\n }\r\n\r\n public getBackNode(node: Page | Configurator) {\r\n let prev: Page | Configurator;\r\n\r\n if (node) {\r\n let parent = node.$parent as Page | Configurator;\r\n\r\n // find the previous item\r\n if (node instanceof Configurator) {\r\n prev = parent.configurators.previous(node, c => c.pages.some(p => p.visible));\r\n }\r\n if (!prev) prev = parent.pages.previous(node as Page, p => p.visible);\r\n\r\n if (prev) {\r\n let n = prev;\r\n while (n) {\r\n // find the last nested child\r\n n = prev.configurators.filter(c => c.pages.some(p => p.visible)).last();\r\n if (!n) n = prev.pages.filter(p => p.visible).last();\r\n if (n) prev = n;\r\n }\r\n } else {\r\n // if there was no siblings, then go to the parent\r\n if (!prev && parent != this.rootConfig) prev = parent;\r\n if (prev instanceof Configurator) prev = this.getBackNode(prev);\r\n }\r\n }\r\n return prev;\r\n }\r\n\r\n public queueRule(ruleAction: () => ng.IPromise) {\r\n if (this.activeRule) {\r\n this.activeRule = this.activeRule.then(() => {\r\n return ruleAction();\r\n });\r\n } else {\r\n this.activeRule = ruleAction();\r\n }\r\n return this.activeRule;\r\n }\r\n\r\n public oncePerCycleRule(): ng.IPromise {\r\n return new KPromise(\r\n (() => {\r\n this.runPricing();\r\n this.calculateNodes();\r\n this.getCurrentConfigForViewerAndSetViewerMode(); //need to set viewerMode before layout rule so the layout rule can show/hide the viewer accordingly\r\n })()\r\n )\r\n .then(() => this.runLayoutRule(this.$scope.config, this.getRuleArgs(this.$scope.config)))\r\n .then(() => !this.loading && this.refreshViewer())\r\n .then(() => {\r\n this.$scope.actionsVisible = this.$scope.config.actions.some(a => a.visible);\r\n this.$timeout(() => {\r\n //this.resizeActionBar();\r\n this.refreshDrawer();\r\n });\r\n }) as any;\r\n }\r\n\r\n private runLoadedRule(config: Configurator, args: ILoadedRuleArgs): Q.IPromise> {\r\n if (!this.$scope.isScene && !config.$ranLoadedRule) {\r\n //scene loaded rule is handled by the viewer\r\n config.$ranLoadedRule = true;\r\n return this.helper.runRuleTypeAsync(config, eRuleType.loaded, args);\r\n }\r\n return new KPromise(>{ parameters: args, hasError: false });\r\n }\r\n\r\n private runningRules: any = {};\r\n private static cycleLimit: number = 2;\r\n /**\r\n * manages bubbling the value rule running up or down. We do this isolated,\r\n * so we don't end up over-running other rules (like validation, pricing, scene).\r\n * Returns a boolean indicating whether the configurator fields were dirty immediately\r\n * after running the value rule (indicating whether something before or during the value\r\n * rule actually modified a field)\r\n * @param config\r\n * @param field\r\n */\r\n public runRuleCycleUnit(config: Configurator, field: Field, bubble = true): ng.IPromise {\r\n if (this.runningRules[config.name] >= ConfiguratorController.cycleLimit) {\r\n console.log(`Rule cycle recursion limit hit for configurator '${config.name}'. Opting out of running`);\r\n return this.$q.when(false);\r\n }\r\n\r\n if (!this.runningRules[config.name]) this.runningRules[config.name] = 1;\r\n else this.runningRules[config.name]++;\r\n\r\n let nestedRulesRan = false;\r\n let ruleArgs = this.getRuleArgs(config, field);\r\n let origNumberOfNesteds = config.getNestedConfigurators().length;\r\n let configWasDirty = false;\r\n\r\n let runRules = this.helper\r\n .runSelects(config)\r\n // value rules\r\n .then(() => this.helper.runRuleTypeAsync(config, eRuleType.value, ruleArgs))\r\n .then(() => {\r\n configWasDirty = config.$fieldsDirty;\r\n // reset $fieldsDirty of this configurator so it doesn't affect a\r\n // parent's decision on whether to run the child's rules\r\n config.$fieldsDirty = false;\r\n })\r\n .then(() => {\r\n // run rule cycle on dirty nesteds\r\n let promises: ng.IPromise[] = [];\r\n config.getNestedConfigurators().forEach(nested => {\r\n /* if the nested configurator was changed by the parent rules OR\r\n if the nested is setup to be always a child, and this parent actually had a change\r\n then we need to run the nested's value rule */\r\n if (nested.$fieldsDirty || (nested.alwaysChild && nested.alwaysChildOf && configWasDirty)) {\r\n nestedRulesRan = true;\r\n // don't bubble the nested rules here. We'll take care of it at the parent level next\r\n promises.push(this.runRuleCycleUnit(nested, null, false));\r\n }\r\n });\r\n return this.$q.all(promises);\r\n })\r\n .then(\r\n (dirtyArr: boolean[]) =>\r\n // after running nested config rule cycles, if this parent is referencing them,\r\n // it now needs to be updated we do this here instead of using the bubbling below\r\n // so that the parent only re - runs it's rules once, instead of once for each nested\r\n nestedRulesRan &&\r\n ((!this.loading && dirtyArr && dirtyArr.some(b => b == true)) || //make sure that one of the nesteds is actually dirty or it's pointless to re-run this config's value rule\r\n (this.loading && origNumberOfNesteds < config.getNestedConfigurators().length)) && // if we are loading, then only bubble if a new nested configurator was added by the value rule\r\n config.bubbleRules &&\r\n this.helper.runRuleTypeAsync(config, eRuleType.value, ruleArgs)\r\n )\r\n .then(() => {\r\n return this.runValidationRule(config, ruleArgs);\r\n })\r\n .then(() => this.helper.runRuleTypeAsync(config, eRuleType.visibility, ruleArgs))\r\n .then(\r\n () =>\r\n // as opposed to the bubbling above, this bubbling is more for the user having changed\r\n // a field value in the nested configurator directly and us sensing that the parent now\r\n // needs to update. (only if we are done loading, since loading bubbles through all\r\n // configurators anyways)\r\n !this.loading &&\r\n bubble &&\r\n config.$parentConfigurator &&\r\n config.$parentConfigurator.bubbleRules &&\r\n this.runRuleCycleUnit(config.$parentConfigurator, null)\r\n )\r\n .then(() => {\r\n delete this.runningRules[config.name];\r\n });\r\n\r\n return runRules.then(() => configWasDirty);\r\n }\r\n\r\n public queueEventRuleType(config: Configurator, ruleType: eRuleType, args: IConfiguratorRuleArgs) {\r\n let rc = config.ruleContainers.find(rc => {\r\n return rc.ruleType.isEqual(ruleType);\r\n });\r\n return this.queueEventRule(config, rc, args);\r\n }\r\n\r\n /** wraps the given delegate to run a rule, and follows it with a rule cycle if the event rule changed something that warrants it */\r\n public queueEventRule(config: Configurator, ruleContainer: RuleContainer, args: IConfiguratorRuleArgs) {\r\n return this.queueRule(() => {\r\n //if there is no rule for the rule type, then cut it off here so we don't run oncePerCycleRule unnecessarily\r\n if (ruleContainer && ruleContainer.js) {\r\n let origNumberOfNesteds = config.getNestedConfigurators().length;\r\n return this.helper.runRuleContainerAsync(ruleContainer, args).then(() => {\r\n let nesteds = config.getNestedConfigurators();\r\n if (\r\n config.$fieldsDirty ||\r\n (this.$scope.layoutConfig && this.$scope.layoutConfig.$layoutSettingsDirty) ||\r\n origNumberOfNesteds != nesteds.length ||\r\n nesteds.some(n => n.$fieldsDirty)\r\n ) {\r\n return this.runRuleCycleUnit(config, null).then(() => this.oncePerCycleRule());\r\n } else if (\r\n ruleContainer.ruleType.isEqual(eRuleType.tabChanged) &&\r\n ruleContainer.references.length\r\n ) {\r\n this.refreshViewer(true);\r\n } else {\r\n this.$scope.$digest(); //because of the way event queueing works, we need to $digest here\r\n }\r\n });\r\n } else {\r\n let result: IJsResult = {\r\n hasError: false,\r\n parameters: args,\r\n };\r\n return new KPromise(result) as any;\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Runs the given function on the configurator given and all of it's child configurators in the direction given\r\n * @param fn\r\n */\r\n public nestedRunTopDown(config: Configurator, fn: (nested: Configurator) => ng.IPromise) {\r\n let nesteds = config.getNestedConfigurators();\r\n return fn(config).then(() => this.$q.all(nesteds.map(n => this.nestedRunTopDown(n, fn))));\r\n }\r\n\r\n public nestedRunBottomsUp(config: Configurator, fn: (nested: Configurator) => ng.IPromise): ng.IPromise {\r\n let nesteds = config.getNestedConfigurators();\r\n let continueRun = () => this.$q.all(nesteds.map(n => this.nestedRunBottomsUp(n, fn)));\r\n if (this.loading && nesteds.some(n => n.alwaysChild)) {\r\n return this.nestedRunTopDown(config, fn)\r\n .then(continueRun)\r\n .then(() => fn(config));\r\n } else {\r\n return continueRun().then(() => fn(config));\r\n }\r\n }\r\n\r\n public runNestedRuleType(\r\n config: Configurator,\r\n nested: Configurator,\r\n ruleType: string,\r\n args?: INestedConfiguratorRuleArgs\r\n ): ng.IPromise> {\r\n if (!args) args = this.getRuleArgs(config);\r\n args.nested = nested;\r\n\r\n let refConfig = config.referencedConfigurators.find(rc => rc.idProduct == nested.idProduct);\r\n let ruleContainer = refConfig.ruleContainers.find(rc => rc.ruleType.isEqual(ruleType));\r\n if (ruleContainer) {\r\n return this.helper.runRuleContainerAsync(ruleContainer, args);\r\n } else {\r\n return this.$q.when(null);\r\n }\r\n }\r\n\r\n public runValidationRule(config: Configurator, ruleArgs: IConfiguratorRuleArgs): ng.IPromise {\r\n config.preValidate(); // call internal validation for fields\r\n return this.helper.runRuleTypeAsync(config, eRuleType.validation, ruleArgs).then(() => {\r\n config.isValid(); //force recalculation of $valid property\r\n });\r\n }\r\n\r\n public runLayoutRule(config: Configurator, ruleArgs: IConfiguratorRuleArgs): ng.IPromise {\r\n return this.helper.runRuleTypeAsync(this.$scope.config, eRuleType.layout, ruleArgs).then(() => {\r\n this.$scope.layoutConfig.$layoutSettingsDirty = false;\r\n if (!this.$scope.layoutLoaded) {\r\n this.$scope.layoutLoaded = true;\r\n if (this.$scope.config.hasRule(eRuleType.layout)) {\r\n /**\r\n * Process UI changes when first running so there is no FOUC.\r\n * Note that we only call this if there is actually a layout rule, because\r\n * otherwise the runRuleTypeAsync above actually resolves synchronously because it's\r\n * a KbPromise, then we get an error on the $digest call that there is already one in\r\n * progress\r\n */\r\n this.$scope.$digest();\r\n }\r\n }\r\n\r\n return this.$scope.resizeScene();\r\n });\r\n }\r\n\r\n public runSubmitRule(): ng.IPromise {\r\n console.log('runSubmitRule');\r\n this.runAsyncRule = false;\r\n this.rootConfig.parameters = this.getParameters();\r\n\r\n return this.queueRule(() => {\r\n return this.nestedRunBottomsUp(this.rootConfig, c => {\r\n let origNumberOfNesteds = c.getNestedConfigurators().length;\r\n let ruleArgs = this.getLoadedRuleArgs(c);\r\n //set all fields to be \"touched\" and re-run validation to satisfy configurator.validationTiming setting\r\n c.getFields().forEach(f => (f.hasBeenTouched = true));\r\n\r\n return this.runValidationRule(c, ruleArgs).then(() => {\r\n return this.helper.runRuleTypeAsync(c, eRuleType.submit, ruleArgs).then(() => {\r\n let nesteds = c.getNestedConfigurators();\r\n //if the submit rule changed any fields or added nested configurators, run another rule cycle\r\n if (\r\n c.$fieldsDirty ||\r\n origNumberOfNesteds != nesteds.length ||\r\n nesteds.some(n => n.$fieldsDirty)\r\n ) {\r\n return this.runRuleCycleUnit(c, null);\r\n }\r\n });\r\n });\r\n }).then(() => {\r\n this.telemetryService.trackEvent('Configurator Submit Rule Run');\r\n });\r\n });\r\n }\r\n\r\n public showErrors() {\r\n return (\r\n this.$scope.isScene ||\r\n this.$scope.isTest ||\r\n this.$rootScope.environment == eEnvironment.dev ||\r\n this.$rootScope.environment == eEnvironment.test\r\n );\r\n }\r\n\r\n public getRuleArgs(config: Configurator, changedField?: Field): ConfiguratorRuleArgs {\r\n let ruleArgs = new ConfiguratorRuleArgs(this);\r\n ruleArgs.user = this.$rootScope.user;\r\n ruleArgs.environment = this.$rootScope.environment;\r\n ruleArgs.baseUrl = this.$rootScope.context.baseUrl;\r\n ruleArgs.configurator = config;\r\n ruleArgs.layoutConfig = this.$scope.layoutConfig;\r\n ruleArgs.kom = config.$manager;\r\n ruleArgs.parentKom = config.$parentConfigurator ? config.$parentConfigurator.$manager : null;\r\n ruleArgs.changedField = changedField;\r\n ruleArgs.logs = new ClientLogger();\r\n ruleArgs.clientLanguage = this.$rootScope.clientLanguage;\r\n ruleArgs.viewerMode = this.$scope.viewerMode;\r\n ruleArgs.isCrm = this.$rootScope.isSfdc || this.$rootScope.isSfdcCpq;\r\n\r\n ruleArgs.parameters = this.getParameters();\r\n\r\n return ruleArgs;\r\n }\r\n\r\n public getLoadedRuleArgs(config: Configurator): IConfiguratorLoadedRuleArgs {\r\n let args = jQuery.extend(this.getRuleArgs(config), {\r\n isEdit: this.$scope.isEdit || (this.$scope.isKinetic && this.$scope.deferLoadedRule),\r\n quoteProduct: this.$scope.isEdit || this.$scope.deferLoadedRule ? this.model : null,\r\n });\r\n return args;\r\n }\r\n public createSceneViewer(scene: IScene): ng.IPromise {\r\n let sceneViewer: SceneViewer;\r\n let viewerScope = this.$scope.$new();\r\n const company = this.$rootScope.company;\r\n const env = this.$rootScope.environment;\r\n\r\n let vArgs = {\r\n //$rootScope: this.$rootScope,\r\n //$http: this.$http,\r\n environment: this.$rootScope.environment,\r\n baseUrl: this.$rootScope.context.baseUrl,\r\n assetRoot: this.$rootScope.context.publicStorageUrl,\r\n clusterEnv: this.$rootScope.context.clusterEnv,\r\n cacheBuster: this.$rootScope.context.cacheBuster,\r\n clientLanguage: this.$rootScope.clientLanguage,\r\n isMobile: this.$rootScope.windowWidth < Utils.MOBILE_WIDTH,\r\n isRender: false,\r\n renderPass: null,\r\n $q: this.$q,\r\n $timeout: this.$timeout,\r\n $injector: this.$injector,\r\n ruleService: this.ruleService,\r\n //uploadService: this.uploadService,\r\n dialogService: this.dialogService,\r\n highlightColor: this.themeService.getActiveTheme().accent,\r\n //$compile: this.$compile,\r\n $scope: viewerScope,\r\n handleRuleError: (ruleName, result) => this.helper.handleRuleError(ruleName, result),\r\n tableArraysDb: this.helper.tableArraysDb,\r\n //helper: this.helper,\r\n elemSelector: '.kb-viewer',\r\n //isEmbed: true,\r\n bare: false,\r\n requestId: null,\r\n // scene: scene,\r\n sceneDb: this.sceneDb,\r\n configSession: this.configSession,\r\n messageCallback: null,\r\n configuratorLoadedPromise: this.configuratorLoadedDeferred.promise,\r\n arLoading: this.$scope.arLoading,\r\n navigateToElement: o => {\r\n this.navigateToElement(o);\r\n },\r\n compileTemplate: (hotspotDiv, scope) => {\r\n return this.$compile(hotspotDiv)(scope as ng.IScope)[0];\r\n },\r\n lastDeploy:\r\n env == eEnvironment.dev\r\n ? 0\r\n : env == eEnvironment.test\r\n ? company.lastTestDeployment\r\n : company.lastProdDeployment,\r\n } as ISceneViewerArgs;\r\n\r\n if (scene.external) {\r\n let cArgs = vArgs as IClaraSceneViewerArgs;\r\n cArgs.sceneService = this.$injector.get(Token.ClaraSceneService.key);\r\n cArgs.playerUrl = this.$rootScope.context.claraV2LibraryUrl;\r\n cArgs.ocLazyLoad = this.ocLazyLoad;\r\n sceneViewer = new ClaraViewer(cArgs);\r\n } else {\r\n sceneViewer = new Kb3dViewer(vArgs);\r\n }\r\n\r\n return sceneViewer.init().then(() => {\r\n viewerScope.$on('$destroy', () => {\r\n sceneViewer.dispose();\r\n });\r\n return sceneViewer;\r\n });\r\n }\r\n\r\n public runSceneAction(config: Configurator, actionName: string): ng.IPromise {\r\n if (this.lastViewerPromise) {\r\n return this.lastViewerPromise.then(() => {\r\n return this.$scope.activeSceneViewer && this.$scope.activeSceneViewer.runAction(actionName);\r\n });\r\n } else {\r\n return this.refreshViewer().then(() => {\r\n return this.$scope.activeSceneViewer && this.$scope.activeSceneViewer.runAction(actionName);\r\n });\r\n }\r\n }\r\n\r\n protected getCurrentConfigForViewerAndSetViewerMode(): Configurator {\r\n let currentConfig = this.rootConfig;\r\n if (this.$scope.selected.page) currentConfig = this.$scope.selected.page.$parentConfigurator;\r\n // find the closest config that should show a 3d viewer\r\n while (currentConfig) {\r\n if (currentConfig.viewerMode == eViewerMode.media || currentConfig.viewerMode == eViewerMode.none) {\r\n break;\r\n } else if (currentConfig.viewerMode == eViewerMode.scene && currentConfig.idScene) {\r\n if (!currentConfig.$parent) break;\r\n // it's nested: we only show it if it's not set to merge scenes with it's parent\r\n let refConfig = currentConfig.$parentConfigurator.referencedConfigurators.find(\r\n rc => rc.idProduct == currentConfig.idProduct\r\n );\r\n if (!refConfig.nestScene) break;\r\n }\r\n\r\n currentConfig = currentConfig.$parentConfigurator;\r\n }\r\n\r\n if (!currentConfig) {\r\n this.$scope.viewerMode = eViewerMode.none;\r\n } else {\r\n this.$scope.viewerMode = currentConfig.viewerMode;\r\n }\r\n\r\n return currentConfig;\r\n }\r\n\r\n public refreshViewer(skipRules = false): ng.IPromise {\r\n if (!this.lastViewerPromise) this.lastViewerPromise = new KPromise(null) as any;\r\n\r\n this.lastViewerPromise = this.lastViewerPromise.then(() => {\r\n let viewerDeferred = this.$q.defer();\r\n let origSceneViewer = this.$scope.activeSceneViewer;\r\n let origConfig = origSceneViewer ? origSceneViewer.uiConfig : null;\r\n let currentConfig = this.getCurrentConfigForViewerAndSetViewerMode();\r\n\r\n if (currentConfig) {\r\n if (this.sceneDb[currentConfig.idScene] && this.sceneDb[currentConfig.idScene].external) {\r\n currentConfig.nestedPath = currentConfig.idScene;\r\n } else {\r\n currentConfig.nestedPath = this.getConfiguratorUniqueKey(currentConfig);\r\n }\r\n\r\n if (currentConfig.viewerMode == eViewerMode.media) {\r\n this.$scope.viewerMediaPath = currentConfig.viewerMediaPath;\r\n viewerDeferred.resolve();\r\n } else if (currentConfig.viewerMode == eViewerMode.scene) {\r\n let clear =\r\n this.rootConfig.clearMemoryWhenSwitchingScenes &&\r\n this.$scope.activeSceneViewer &&\r\n this.$scope.activeSceneViewer.scene.id != currentConfig.idScene;\r\n\r\n /**\r\n * for kb3d if we are clearing memory we just dispose of the old viewer and make a new one\r\n */\r\n if (clear && !this.sceneDb[currentConfig.idScene].external) {\r\n delete this.sceneViewerDb[currentConfig.nestedPath];\r\n origSceneViewer.dispose();\r\n this.$scope.activeSceneViewer = null;\r\n clear = false;\r\n }\r\n\r\n if (clear) {\r\n this.$timeout(() => {\r\n this.sceneViewerDb[currentConfig.nestedPath] = this.$scope.activeSceneViewer;\r\n this.$scope.activeSceneViewer\r\n .loadScene({\r\n scene: this.sceneDb[currentConfig.idScene],\r\n clearMemory: true,\r\n config: currentConfig,\r\n isStandalone: this.$scope.isScene,\r\n isRenderContext: false,\r\n })\r\n .then(() => viewerDeferred.resolve());\r\n }, 0);\r\n } else {\r\n this.$scope.activeSceneViewer = this.sceneViewerDb[currentConfig.nestedPath];\r\n if (this.$scope.activeSceneViewer) {\r\n // execute scene on next frame so configurator appears responsive\r\n this.$timeout(() => {\r\n // if we are switching configurators, but keeping the same sceneViewer,\r\n // then we need to clear the clickDb\r\n if (this.$scope.activeSceneViewer.uiConfig != currentConfig) {\r\n this.$scope.activeSceneViewer.clearHandlers();\r\n }\r\n // set the uiConfig of the viewer\r\n if (this.$scope.activeSceneViewer.sceneConfig.idProduct == currentConfig.idProduct) {\r\n currentConfig.$sceneConfigurator = this.$scope.activeSceneViewer.sceneConfig;\r\n this.$scope.activeSceneViewer.sceneConfig.$uiConfigurator = currentConfig;\r\n this.$scope.activeSceneViewer.uiConfig = currentConfig;\r\n }\r\n //only skip rules if we are told to and we haven't switched scene viewers\r\n if (skipRules && this.$scope.activeSceneViewer.uiConfig == origConfig) {\r\n viewerDeferred.resolve();\r\n } else {\r\n this.$scope.activeSceneViewer\r\n .runRules(true)\r\n //.then(result => this.helper.handleRuleError(eRuleType.scene, result))\r\n .then(() => viewerDeferred.resolve());\r\n }\r\n }, 0);\r\n } else {\r\n // init the sceneViewer which also runs the rules\r\n //if there is no viewer in the layout, then we skip\r\n if (!this.isViewerInLayout()) {\r\n viewerDeferred.resolve();\r\n } else {\r\n this.waitForViewerReady().then(\r\n () => {\r\n let scene = this.sceneDb[currentConfig.idScene];\r\n this.createSceneViewer(scene).then(sceneViewer => {\r\n this.$scope.activeSceneViewer = sceneViewer;\r\n this.sceneViewerDb[currentConfig.nestedPath] =\r\n this.$scope.activeSceneViewer;\r\n this.$scope.activeSceneViewer\r\n .loadScene({\r\n scene,\r\n clearMemory: this.rootConfig.clearMemoryWhenSwitchingScenes,\r\n config: currentConfig,\r\n isStandalone: this.$scope.isScene,\r\n isRenderContext: false,\r\n })\r\n .then(() => viewerDeferred.resolve());\r\n });\r\n },\r\n err => {\r\n viewerDeferred.reject(err);\r\n }\r\n );\r\n }\r\n }\r\n }\r\n } else {\r\n viewerDeferred.resolve();\r\n }\r\n } else {\r\n viewerDeferred.resolve();\r\n }\r\n\r\n // set other viewers to hide\r\n Object.keys(this.sceneViewerDb).forEach(key => {\r\n if (\r\n this.$scope.viewerMode != eViewerMode.scene ||\r\n this.$scope.activeSceneViewer !== this.sceneViewerDb[key]\r\n ) {\r\n this.sceneViewerDb[key].hide();\r\n } else {\r\n this.sceneViewerDb[key].show();\r\n }\r\n });\r\n\r\n return viewerDeferred.promise;\r\n });\r\n // console.log(this.configuratorMap);\r\n // console.log(this.nestedSceneMap);\r\n return this.lastViewerPromise;\r\n }\r\n\r\n public isViewerInLayout() {\r\n return this.$scope.config.getChildrenOfType(CToken.Viewer).some(v => v.visible);\r\n }\r\n\r\n public waitForViewerReady(): Q.IPromise {\r\n if (!this.isViewerInLayout()) {\r\n return new KPromise(null);\r\n } else {\r\n let elemDefer = Q.defer();\r\n let waitedFor = 0;\r\n let wait = 30;\r\n let check = () => {\r\n let parentElem = document.querySelector('.kb-viewer') as HTMLElement;\r\n if (parentElem && parentElem.getBoundingClientRect().height > 0) {\r\n if (waitedFor) console.log(`waited ${waitedFor}ms for viewer ready`);\r\n elemDefer.resolve();\r\n } else {\r\n setTimeout(() => {\r\n waitedFor += wait;\r\n check();\r\n }, wait);\r\n }\r\n };\r\n check();\r\n return elemDefer.promise as Q.IPromise;\r\n }\r\n }\r\n\r\n public hasPricing() {\r\n return (\r\n this.rootConfig.hasPricingRule ||\r\n this.hasNestedPricing() ||\r\n (this.$scope.isTest && this.rootConfig.ruleContainers.some(rc => rc.ruleType == eRuleType.pricing))\r\n );\r\n }\r\n\r\n public runPricing(): ng.IPromise {\r\n let promise = new KPromise(null) as any;\r\n if (this.hasPricing()) {\r\n let configuredProduct = this.rootConfig.getConfiguredProduct();\r\n promise = this.lastPricingPromise = this.$http\r\n .post('/api/products/' + this.$scope.entity.id + '/pricing', configuredProduct, {\r\n tracker: this.$scope.pricingTracker,\r\n })\r\n .then(\r\n response => {\r\n this.rootConfig.priceObject = this.$scope.priceObject = response.data;\r\n },\r\n error => {\r\n this.helper.handleRuleError('Pricing Rule', {\r\n hasError: true,\r\n error: new Error(error.data.error),\r\n parameters: this.getRuleArgs(this.rootConfig),\r\n });\r\n }\r\n );\r\n }\r\n return promise;\r\n }\r\n\r\n public addLevelsToPricing(item: IPriceItemBase, level: number = -1) {\r\n let o: any = item;\r\n if (o) {\r\n o.$level = level;\r\n item.items && item.items.forEach(i => this.addLevelsToPricing(i, level + 1));\r\n }\r\n }\r\n\r\n public hasNestedPricing() {\r\n return this.rootConfig\r\n .getNestedConfigurators()\r\n .some(\r\n nested =>\r\n nested.hasPricingRule &&\r\n this.rootConfig.referencedConfigurators.find(rc => rc.idProduct == nested.idProduct).nestPriceObject\r\n );\r\n }\r\n\r\n public setScene(configurator: Configurator, idScene: number): ng.IPromise {\r\n if (configurator.idScene != idScene) {\r\n configurator.idScene = idScene;\r\n configurator.$nestedSceneId = null;\r\n configurator.$sceneConfigurator = null;\r\n\r\n return this.refreshViewer();\r\n }\r\n\r\n return new KPromise(null) as any;\r\n }\r\n\r\n public trackConfigPageView(page: Page) {\r\n if (page) {\r\n let path = page.name;\r\n let parent = page.$parentConfigurator;\r\n while (parent.$parentConfigurator) {\r\n path = `${parent.name}/${path}`;\r\n parent = parent.$parentConfigurator;\r\n }\r\n this.telemetryService.trackEvent('Configurator Page View', { pageName: path });\r\n }\r\n }\r\n\r\n private getParameters() {\r\n var parameters = Utils.extend(this.$location.search(), this.$scope.embedParameters);\r\n\r\n // combine query string parameters with sfdc parameters\r\n if (this.$rootScope.context.sfdcCanvasRequest) {\r\n parameters = Utils.extend(\r\n this.$rootScope.context.sfdcCanvasRequest.context.environment.parameters,\r\n parameters\r\n );\r\n if (this.$rootScope.isSfdcCpq) {\r\n parameters.sfdcQuote = this.sfdcCpqPayload.fullQuote;\r\n parameters.sfdcConfiguredProductId = this.sfdcCpqPayload.data.product.configuredProductId;\r\n parameters.sfdcQuoteLine = this.sfdcCpqPayload?.data?.product;\r\n }\r\n }\r\n return parameters;\r\n }\r\n\r\n public scheduledRules: any[];\r\n public runContinuousAsyncRule(id: string, timeSeconds: number) {\r\n if (!this.scheduledRules) this.scheduledRules = [];\r\n\r\n \r\n if (this.scheduledRules.find(a => a.id == id)) {\r\n this.cancelScheduledRule(id);\r\n }\r\n \r\n let interval = this.$interval(() => {\r\n if (this.$rootScope && this.runAsyncRule) {\r\n this.$rootScope.showSpinner = false;\r\n return this.helper.runActionByIdAsync(this.rootConfig, id).then(result => {\r\n this.$rootScope.showSpinner = true;\r\n this.$rootScope.$apply();\r\n\r\n // TODO: Will need to run this conditionally on whether a rule cycle\r\n // actually needs to be run after an interval is run.\r\n //this.runRuleCycleUnit(this.$scope.config, null);\r\n });\r\n }\r\n \r\n }, timeSeconds * 1000);\r\n\r\n this.scheduledRules.push({\r\n id: id,\r\n promise: interval\r\n });\r\n\r\n }\r\n\r\n public cancelScheduledRule(id: string) {\r\n if (this.scheduledRules && this.scheduledRules.length > 0) {\r\n let runningRule = this.scheduledRules.find(a => a.id == id);\r\n if (runningRule) {\r\n this.$interval.cancel(runningRule.promise);\r\n this.scheduledRules.remove(runningRule);\r\n }\r\n }\r\n\r\n return;\r\n }\r\n\r\n public runTimeoutRule(func: Function, timeSeconds: number) {\r\n\r\n this.$timeout(() => {\r\n //this.$rootScope.showSpinner = false;\r\n if (this.$rootScope && this.runAsyncRule) {\r\n this.$rootScope.showSpinner = false;\r\n let res = func();\r\n if (res instanceof Promise) {\r\n return res.then(() => {\r\n this.$rootScope.showSpinner = true;\r\n });\r\n } else {\r\n return res;\r\n }\r\n \r\n // return this.helper.runActionByIdAsync(this.rootConfig, id).then(() => {\r\n // this.$rootScope.showSpinner = true;\r\n // this.$rootScope.$apply();\r\n // });\r\n }\r\n\r\n }, timeSeconds * 1000);\r\n }\r\n\r\n protected fillSourcedTables(session: IConfiguratorSession): ng.IPromise {\r\n let tablePromise: ng.IPromise = new KPromise(null) as any;\r\n if (session.sourcedTableIds && session.sourcedTableIds.length) {\r\n return this.api.tables.getBatch({ ids: session.sourcedTableIds }).then(sourcedTables => {\r\n if (sourcedTables && sourcedTables.length) {\r\n session.tables.pushArray(sourcedTables);\r\n }\r\n });\r\n } else {\r\n return new KPromise(null) as any;\r\n }\r\n }\r\n}\r\n","import { NgView } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { ApiService } from \"@app/services/api.service\";\r\nimport { AuthService } from \"@app/services/auth.service\";\r\nimport { DrawerService } from \"@app/services/drawer.service\";\r\nimport { QuoteService } from \"@app/services/quote.service\";\r\nimport { BaseController, IBaseScope } from \"@app/views/base.view\";\r\nimport { IProduct, IRootScope } from \"@models\";\r\nimport { icons } from \"@tools\";\r\nimport { StateService } from \"@uirouter/angularjs\";\r\n\r\nexport interface IProductCompareScope extends IBaseScope {\r\n model: IProduct[];\r\n removeProduct: (id: number) => void;\r\n addToQuote: (product: IProduct) => void;\r\n}\r\n\r\n@NgView({\r\n token: Token.ProductCompareView,\r\n dependencies: [\r\n Token.$Scope,\r\n Token.$State,\r\n Token.$RootScope,\r\n Token.ApiService,\r\n Token.DrawerService,\r\n Token.QuoteService,\r\n Token.Model\r\n ],\r\n resolves: [\r\n {\r\n name: \"model\",\r\n dependencies: [\r\n Token.ApiService,\r\n Token.AuthService,\r\n Token.$StateParams,\r\n Token.$RootScope,\r\n ],\r\n fn: (\r\n api: ApiService,\r\n authService: AuthService,\r\n $stateParams: any,\r\n $rootScope: IRootScope\r\n ) => {\r\n return authService.authPromise.then(() =>\r\n api.products.getBatch({ ids: $stateParams.ids }, $rootScope.contentTracker)\r\n // api.products.search({ \r\n // query: `id:(${$stateParams.ids.join(\" OR \")})`\r\n // }, $rootScope.contentTracker)\r\n );\r\n }\r\n }\r\n ]\r\n})\r\nexport class ProductCompareController extends BaseController {\r\n\r\n constructor(\r\n $scope: IProductCompareScope,\r\n $state: StateService,\r\n $rootScope: IRootScope,\r\n api: ApiService,\r\n drawerService: DrawerService,\r\n quoteService: QuoteService,\r\n model: IProduct[]\r\n ) {\r\n\r\n super();\r\n drawerService.setHelpUrl(\"Products\");\r\n drawerService.pageTitle = loc.productcomparison;\r\n drawerService.pageType = loc.product;\r\n drawerService.pageIcon = icons.cast;\r\n\r\n $scope.model = model;\r\n \r\n\r\n $scope.addToQuote = (product: IProduct) => {\r\n quoteService.addProduct({ idProduct: product.id, qty: product.minQty, addLocally: true });\r\n };\r\n\r\n $scope.removeProduct = (id) => {\r\n $rootScope.comparedProducts.removeWhere(p => p == id);\r\n if ($rootScope.comparedProducts.length > 0) {\r\n $state.go(\"kb.productCompare\", { ids: $rootScope.comparedProducts });\r\n } else {\r\n $state.go(\"kb.products\");\r\n }\r\n };\r\n }\r\n}\r\n","import { NgView } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { ApiService } from \"@app/services/api.service\";\r\nimport { AuthService } from \"@app/services/auth.service\";\r\nimport { DialogService } from \"@app/services/dialog.service\";\r\nimport { DrawerService } from \"@app/services/drawer.service\";\r\nimport { QuoteService } from \"@app/services/quote.service\";\r\nimport { BaseController, IBaseScope } from \"@app/views/base.view\";\r\nimport { eAlertType, IProduct, IRootScope, IVolumeDiscount } from \"@models\";\r\nimport { icons } from \"@tools\";\r\nimport { StateService } from \"@uirouter/angularjs\";\r\n\r\nexport interface IProductScope extends IBaseScope {\r\n model: IProduct;\r\n selectedMedia: string;\r\n add: () => void;\r\n selectMedia: (path: string) => void;\r\n qty: number;\r\n relatedProducts: IProduct[];\r\n search: () => void;\r\n addToQuote: () => void;\r\n getVolumeDiscountText: (volumeDiscount: IVolumeDiscount) => string;\r\n}\r\n\r\n@NgView({\r\n token: Token.ProductView,\r\n dependencies: [\r\n Token.$Scope,\r\n Token.$State,\r\n Token.$RootScope,\r\n Token.ApiService,\r\n Token.DrawerService,\r\n Token.QuoteService,\r\n Token.DialogService,\r\n Token.Model\r\n ],\r\n resolves: [\r\n {\r\n name: \"model\",\r\n dependencies: [\r\n Token.ApiService,\r\n Token.AuthService,\r\n Token.$StateParams,\r\n Token.$RootScope,\r\n ],\r\n fn: (\r\n api: ApiService,\r\n authService: AuthService,\r\n $stateParams: any,\r\n $rootScope: IRootScope\r\n ) => {\r\n return authService.authPromise.then(() =>\r\n api.products.getById($stateParams.id, $rootScope.contentTracker)\r\n );\r\n }\r\n }\r\n ]\r\n})\r\nexport class ProductController extends BaseController {\r\n\r\n constructor(\r\n $scope: IProductScope,\r\n $state: StateService,\r\n $rootScope: IRootScope,\r\n api: ApiService,\r\n drawerService: DrawerService,\r\n quoteService: QuoteService,\r\n dialogService: DialogService,\r\n model: IProduct\r\n ) {\r\n\r\n super();\r\n drawerService.setHelpUrl(\"Products\");\r\n drawerService.pageTitle = $scope.model.name;\r\n drawerService.pageType = loc.product;\r\n drawerService.pageIcon = icons.standardProducts;\r\n\r\n $scope.model = model;\r\n $scope.qty = $scope.model.minQty;\r\n\r\n if (model.images && model.images.length > 0) {\r\n $scope.selectedMedia = model.images[0].imagePath;\r\n }\r\n\r\n $scope.selectMedia = (path: string) => {\r\n $scope.selectedMedia = path;\r\n };\r\n\r\n $scope.addToQuote = () => {\r\n quoteService.addProduct({ idProduct: $scope.model.id, qty: $scope.qty, addLocally: true });\r\n };\r\n\r\n $scope.getVolumeDiscountText = (volumeDiscount: IVolumeDiscount) => {\r\n let result = volumeDiscount.qty.toString();\r\n let nextTier: IVolumeDiscount = null; \r\n let orderedVolumeDiscounts = $scope.model.volumeDiscounts.sort((a, b) => a.qty - b.qty);\r\n for (var i = 0; i < orderedVolumeDiscounts.length; i++) {\r\n if (orderedVolumeDiscounts[i].qty == volumeDiscount.qty) {\r\n nextTier = orderedVolumeDiscounts[i + 1];\r\n break;\r\n }\r\n }\r\n if (nextTier) {\r\n result += \" \" + loc.to + \" \" + (nextTier.qty - 1).toString() + \" \" + loc.units;\r\n }\r\n else {\r\n result += \" \" + loc.units + \" \" + loc.andabove + \": \"; \r\n }\r\n return result;\r\n }\r\n\r\n api.products.searchByCategory({\r\n query: (model.relatedProductsQuery ? model.relatedProductsQuery : model.name) + \" -id:\" + model.id,\r\n take: 5,\r\n skip: 0\r\n }).then(r => $scope.relatedProducts = r);\r\n\r\n // add drawers\r\n if (model.isConfigured) {\r\n let drConfigure = drawerService.addDrawer(\r\n icons.gear,\r\n \"Configure\",\r\n () => $state.go(\"kb.configurator\", { id: model.id })\r\n );\r\n } else {\r\n let drAdd = drawerService.addDrawer(\r\n icons.add,\r\n loc.addtoquote,\r\n $scope.addToQuote\r\n );\r\n }\r\n\r\n if (!$rootScope.comparedProducts.contains($scope.model.id)) {\r\n drawerService.addDrawer(\r\n icons.cast,\r\n loc.compare,\r\n () => {\r\n if ($rootScope.comparedProducts.length >= 4) {\r\n dialogService.alert({\r\n msg: loc.msg_productcomparisonlimit,\r\n type: eAlertType.info\r\n })\r\n } else {\r\n $rootScope.comparedProducts.push($scope.model.id);\r\n $state.go(\"kb.products\");\r\n }\r\n }\r\n );\r\n }\r\n\r\n }\r\n}\r\n","import { NgView } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { ApiService } from \"@app/services/api.service\";\r\nimport { AuthService } from \"@app/services/auth.service\";\r\nimport { KbService } from \"@app/services/kb.service\";\r\nimport { QuoteService } from \"@app/services/quote.service\";\r\nimport { SearchService } from \"@app/services/search.service\";\r\nimport { eFilterControl, eFilterSource, eFilterType, eProductSortBy, ICategoryAttribute, ICategoryNode, IFilter, IProduct, IProductSearchArgs, IProductSuggestPayload, IRootScope, ISavedSearch, meta } from \"@models\";\r\nimport { KPromise } from \"@rules\";\r\nimport { icons } from \"@tools\";\r\nimport { IPromiseTracker } from \"angular\";\r\nimport { ISearchBinding, ISearchScope, SearchController } from \"../search.view\";\r\n\r\n// tslint:disable:interface-name\r\ninterface $IProduct extends IProduct {\r\n $addQty?: number;\r\n}\r\ninterface $ICategoryNode extends ICategoryNode {\r\n $parent?: ICategoryNode;\r\n}\r\n\r\nexport interface IProductSavedSearch extends ISavedSearch{\r\n selectedCategoryId?: number;\r\n}\r\n\r\nexport interface IProductsBinding extends ISearchBinding{\r\n selectedCategory: ICategoryNode;\r\n search?: IProductSavedSearch;\r\n}\r\n\r\nexport interface IProductsScope extends ISearchScope {\r\n binding: IProductsBinding;\r\n categories: ICategoryNode[];\r\n imageMode: boolean;\r\n setToImageMode: () => void;\r\n setToListMode: () => void;\r\n addToQuote: (product: IProduct, qty: number) => void;\r\n translateSuggestion: (item: IProductSuggestPayload) => string;\r\n attributeDb: { [name: string]: ICategoryAttribute };\r\n getChildCategories: (cat: ICategoryNode) => number[];\r\n}\r\n\r\n@NgView({\r\n token: Token.ProductsView,\r\n dependencies: [\r\n Token.$Scope,\r\n Token.SearchService,\r\n Token.KbService,\r\n Token.QuoteService,\r\n Token.Categories\r\n ],\r\n resolves: [\r\n {\r\n name: \"categories\",\r\n dependencies: [\r\n Token.$RootScope,\r\n Token.AuthService,\r\n Token.ApiService\r\n ],\r\n fn: ($rootScope: IRootScope, authService: AuthService, api: ApiService) => {\r\n return authService.authPromise.then(() => {\r\n return api.categories.tree({ onlyActiveCategories: true }, $rootScope.contentTracker).then(r => {\r\n r.unshift({ name: loc.all, id: -1 } as ICategoryNode);\r\n return r;\r\n });\r\n });\r\n }\r\n }\r\n ]\r\n})\r\nexport class ProductsController extends SearchController {\r\n\r\n constructor(\r\n protected $scope: IProductsScope,\r\n public agg: SearchService,\r\n private kbService: KbService,\r\n private quoteService: QuoteService,\r\n private categories: ICategoryNode[]\r\n ) {\r\n\r\n super($scope, agg, true);\r\n\r\n agg.drawerService.setHelpUrl(\"Products\");\r\n agg.drawerService.pageType = loc.products;\r\n agg.drawerService.pageIcon = icons.products;\r\n\r\n $scope.categories = categories;\r\n this.flatCategories = categories.flatten(c => c.items as ICategoryNode[]);\r\n $scope.attributeDb = {};\r\n for (let c of this.flatCategories) {\r\n if (c.attributes) {\r\n for (let a of c.attributes) {\r\n $scope.attributeDb[a.id] = a;\r\n }\r\n }\r\n }\r\n $scope.savedSearchEnabled = false;\r\n $scope.customResults = true;\r\n \r\n if (agg.$state.params.imagemode) {\r\n $scope.imageMode = (agg.$state.params.imagemode == \"true\");\r\n } else {\r\n $scope.imageMode = agg.$rootScope.context.companySettings.displayProductsInImageModeByDefault;\r\n }\r\n\r\n $scope.setToImageMode = () => {\r\n $scope.imageMode = true;\r\n // pageSize = 35;\r\n };\r\n\r\n $scope.setToListMode = () => {\r\n $scope.imageMode = false;\r\n // pageSize = 11;\r\n };\r\n\r\n $scope.getChildCategories = (cat) => {\r\n return this.getChildCategories(cat);\r\n }\r\n \r\n $scope.translateSuggestion = item => {\r\n let name = item.name;\r\n if (agg.$rootScope.companySettings.defaultLanguage != agg.$rootScope.clientLanguage && item.translations) {\r\n let translation = item.translations.find(t => t.languageIso == agg.$rootScope.clientLanguage);\r\n if (translation) {\r\n name = translation.name || item.name;\r\n }\r\n }\r\n return name;\r\n };\r\n\r\n\r\n // when the category selection is changed, fire a search\r\n $scope.$watch(\"binding.selectedCategory\", (newVal: ICategoryNode, oldVal) => {\r\n if (newVal !== oldVal) {\r\n this.$scope.binding.search.selectedCategoryId = newVal.id;\r\n this.refreshAttributeFilters();\r\n $scope.reload();\r\n }\r\n });\r\n \r\n\r\n let addProductPromise: any = new KPromise(null);\r\n $scope.addToQuote = (product, qty) => {\r\n if (product.isConfigured) {\r\n agg.$state.go(\"kb.configurator\", { id: product.id });\r\n } else {\r\n kbService.fly(\"#product_\" + product.id.toString() + \"_image\", \"#product-fly-target\", () => {\r\n addProductPromise = addProductPromise.then(() => {\r\n return quoteService.addProduct({ idProduct: product.id, qty, addLocally: true });\r\n });\r\n });\r\n }\r\n };\r\n\r\n this.init();\r\n this.loadSelectedCategory();\r\n this.refreshAttributeFilters();\r\n }\r\n\r\n protected flatCategories: ICategoryNode[] = [];\r\n\r\n public preInit() {\r\n \r\n }\r\n\r\n public client(api: ApiService) {\r\n return api.products;\r\n }\r\n \r\n public getQueryStringParams(): {} {\r\n return {imagemode: this.$scope.imageMode};\r\n }\r\n\r\n public searchCall(args: IProductSearchArgs, tracker: IPromiseTracker): ng.IPromise {\r\n args.categoryIds = [];\r\n if (this.$scope.binding.selectedCategory.id >= 0) {\r\n args.categoryIds = this.getChildCategories(this.$scope.binding.selectedCategory);\r\n }\r\n return this.client(this.agg.api).searchByCategory(args, tracker);\r\n }\r\n\r\n public loadedFromQueryString(search: IProductSavedSearch) {\r\n this.loadSelectedCategory();\r\n }\r\n\r\n public massageResults(items: $IProduct[]) {\r\n //add a property to the product for the UI to control the qty getting added to the quote\r\n items.forEach(p => p.$addQty = p.minQty);\r\n }\r\n\r\n public loadSelectedCategory() {\r\n if (this.$scope.binding.search.selectedCategoryId == null) this.$scope.binding.search.selectedCategoryId = -1;\r\n this.$scope.binding.selectedCategory = this.getCategory(this.$scope.categories, this.$scope.binding.search.selectedCategoryId);\r\n\r\n this.agg.$timeout(() => {\r\n this.expandToSelectedCategory();\r\n }, 0);\r\n }\r\n\r\n public newSearch(): IProductSavedSearch { \r\n return {\r\n selectedCategoryId: -1,\r\n modelType: meta.Product.$name,\r\n sortField: \"score\",\r\n descending: true,\r\n filters: (() => {\r\n let filters: IFilter[] = [];\r\n filters.push(\r\n {\r\n type: eFilterType.sort,\r\n label: loc.sortby,\r\n control: eFilterControl.select,\r\n sourceType: eFilterSource.productSorts,\r\n valueField: \"value\",\r\n labelField: \"label\",\r\n values: [eProductSortBy.relevance],\r\n sticky: true\r\n }\r\n );\r\n\r\n filters.pushArray(this.getFiltersFromMeta(meta.Product.$name, true));\r\n return filters;\r\n })()\r\n };\r\n }\r\n\r\n protected getCategory(cats: ICategoryNode[], id: number): ICategoryNode {\r\n if (cats) {\r\n for (let cat of cats) {\r\n if (cat.id == id) {\r\n return cat;\r\n }\r\n\r\n let match = this.getCategory(cat.items, id);\r\n if (match) {\r\n return match;\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /** gets an array of the selected category id and all of it's children id's used for filtering the search results*/\r\n protected getChildCategories(cat: ICategoryNode): number[] {\r\n let ids: number[] = [];\r\n ids.push(cat.id);\r\n\r\n cat.items.forEach(child => {\r\n ids = ids.concat(this.getChildCategories(child));\r\n });\r\n\r\n return ids;\r\n }\r\n\r\n protected expandToSelectedCategory() {\r\n let addParentRef = (cats: $ICategoryNode[], parent: $ICategoryNode) => {\r\n cats.forEach(cat => {\r\n cat.$parent = parent;\r\n if (cat.items) addParentRef(cat.items, cat);\r\n });\r\n };\r\n\r\n addParentRef(this.$scope.categories, null);\r\n\r\n let selectedAncestors: $ICategoryNode[] = [];\r\n let p = this.$scope.binding.selectedCategory as $ICategoryNode;\r\n while (p) {\r\n selectedAncestors.push(p);\r\n p = p.$parent;\r\n }\r\n\r\n selectedAncestors.forEach(a => a.expanded = true);\r\n }\r\n\r\n public refreshAttributeFilters() {\r\n let availableAtts = this.getSelectedCategoryAttributes();\r\n //remove available attribute filters\r\n this.$scope.availableFilters.removeWhere(f => f.type == eFilterType.attribute);\r\n //remove any existing filters that are referencing attributes no longer applicable\r\n this.$scope.binding.search.filters.removeWhere(f => f.type == eFilterType.attribute && !availableAtts.some(a => a.name == f.fieldName));\r\n\r\n let attFilters = this.$scope.binding.search.filters.filter(f => f.type == eFilterType.attribute);\r\n for (let a of availableAtts) {\r\n if (!attFilters.find(f => f.attributeId == a.id)) { //only add the attribute filter it if it's not already a filter\r\n let f: IFilter = {\r\n type: eFilterType.attribute,\r\n fieldName: a.name,\r\n label: a.name,\r\n fieldType: a.type,\r\n sourceType: eFilterSource.attributes,\r\n values: [null],\r\n attributeId: a.id\r\n };\r\n if (a.default) {\r\n this.$scope.binding.search.filters.push(f);\r\n } else {\r\n this.$scope.availableFilters.push(f);\r\n }\r\n }\r\n }\r\n\r\n this.fillFilters(); //fill the filters again so it fills the attribute filters\r\n }\r\n\r\n protected getSelectedCategoryAttributes(): ICategoryAttribute[] {\r\n let parentCats: { [id: string]: ICategoryNode } = {};\r\n let selectedCat = this.$scope.binding.selectedCategory;\r\n this.flatCategories.filter(c => selectedCat.lft >= c.lft && selectedCat.rgt <= c.rgt).forEach(c => parentCats[c.id] = c);\r\n\r\n return Object.values(parentCats).selectMany(c => c.attributes);\r\n }\r\n}\r\n","\r\nimport { NgView } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { ApiService } from \"@app/services/api.service\";\r\nimport { QuoteService } from \"@app/services/quote.service\";\r\nimport { SearchService } from \"@app/services/search.service\";\r\nimport { ISearchScope, SearchController } from \"@app/views/search.view\";\r\nimport { eFieldType, eFilterControl, eFilterSource, eFilterType, IFilter, IQuote, IQuoteProduct, ISavedSearch, meta } from \"@models\";\r\nimport { icons } from \"@tools\";\r\n\r\nexport interface IConfiguredProductsScope extends ISearchScope {\r\n fieldChange: (filter: IFilter) => void;\r\n // getFilterControlForField: (fieldName: string) => string;\r\n\r\n showCopyToActiveQuoteBtn: (qp: IQuoteProduct) => boolean;\r\n showCopyToNewQuoteBtn: (qp: IQuoteProduct) => boolean;\r\n copyProductToActiveQuote: (qp: IQuoteProduct) => ng.IPromise;\r\n copyProductToNewQuote: (qp: IQuoteProduct) => ng.IPromise;\r\n}\r\n\r\n@NgView({\r\n token: Token.ConfiguredProductsView,\r\n inherit: [Token.SearchView],\r\n dependencies: [\r\n Token.QuoteService,\r\n ]\r\n})\r\nexport class ConfiguredProductsController extends SearchController {\r\n\r\n constructor(\r\n public $scope: IConfiguredProductsScope,\r\n agg: SearchService,\r\n quoteService: QuoteService\r\n ) {\r\n\r\n super(\r\n $scope,\r\n agg\r\n );\r\n agg.drawerService.setHelpUrl(\"Quotes\");\r\n agg.drawerService.pageType = loc.configuredproducts;\r\n agg.drawerService.pageIcon = icons.quote;\r\n\r\n $scope.binding.search.modelType = meta.QuoteProduct.$name;\r\n $scope.savedSearchEnabled = true;\r\n this.refreshSavedSearches();\r\n $scope.modelTypes = [\r\n { type: meta.Quote.$name, label: \"Quotes\", state: \"kb.quotes\" },\r\n { type: meta.QuoteProduct.$name, label: \"Configured Products\", state: \"kb.configuredProducts\" }\r\n ];\r\n\r\n this.massageFilters($scope.availableFilters);\r\n $scope.availableFilters.pushArray([\r\n this.getWhereFieldFilter()\r\n ]);\r\n\r\n let fieldsDb: { [name: string]: { id; name; type; } } = {};\r\n $scope.$watch(\"binding.search.filters[0].values[0]\", (newVal: number, oldVal) => {\r\n if (newVal) {\r\n agg.api.configurators.searchFields(newVal).then(r => {\r\n fieldsDb = {};\r\n r.forEach(field => fieldsDb[field.name] = field);\r\n $scope.filterSource[eFilterSource.fields] = r;\r\n });\r\n }\r\n });\r\n\r\n // $scope.getFilterControlForField = (fieldName) => {\r\n // var field = fieldsDb[fieldName];\r\n // var fieldType = field ? field.type : eFieldType.text;\r\n // if (fieldType == eFieldType.number)\r\n // return eFilterControl.numberRange;\r\n // else if (fieldType == eFieldType.boolean)\r\n // return eFilterControl.checkbox;\r\n // else\r\n // return eFilterControl.text;\r\n // };\r\n\r\n $scope.fieldChange = filter => {\r\n let field = fieldsDb[filter.fieldName];\r\n let fieldType = field ? field.type : eFieldType.text;\r\n filter.fieldType = fieldType;\r\n if (fieldType == eFieldType.number) {\r\n filter.control = eFilterControl.numberRange;\r\n } else if (fieldType == eFieldType.boolean) {\r\n filter.control = eFilterControl.checkbox;\r\n } else {\r\n filter.control = eFilterControl.text;\r\n }\r\n };\r\n\r\n $scope.showCopyToActiveQuoteBtn = (qp) => {\r\n /** only show this 'copy to active quote' button if we are not in the active quote, and the active quote allows modifying products */\r\n return (\r\n quoteService.quote\r\n && quoteService.canModifyProductsOfQuote(quoteService.quote)\r\n && !agg.$rootScope.isSfdc //this should never happen in CRM integration\r\n );\r\n };\r\n\r\n $scope.showCopyToNewQuoteBtn = (qp) => {\r\n return !agg.$rootScope.isSfdc; //creating a new quote in this way would break the CRM integration\r\n }\r\n\r\n $scope.copyProductToActiveQuote = (qp) => {\r\n return quoteService.copyProductToActiveQuote(qp.id).then(r => {\r\n quoteService.goToQuote();\r\n });\r\n }\r\n\r\n $scope.copyProductToNewQuote = qp => {\r\n return quoteService.copyProductToNewQuote(qp.id).then(r => {\r\n quoteService.goToQuote();\r\n });\r\n }\r\n\r\n\r\n agg.drawerService.addDrawer(icons.clone, loc.clone, () => this.clone());\r\n agg.drawerService.addDrawer(icons.deleter, loc.deleter, () => this.deleteItems());\r\n }\r\n public client(api: ApiService) {\r\n if (this.agg.$rootScope.company.useDatabaseSearch){\r\n return api.quoteProducts;\r\n } else {\r\n return api.quotes;\r\n }\r\n }\r\n\r\n public newSearch(): ISavedSearch {\r\n return {\r\n modelType: meta.QuoteProduct.$name,\r\n sortField: \"modifiedDate\",\r\n descending: true,\r\n filters: (() => {\r\n let filters: IFilter[] = [];\r\n filters.push(\r\n {\r\n type: eFilterType.property,\r\n property: \"idProduct\",\r\n label: \"Product Type\",\r\n control: eFilterControl.select,\r\n sourceType: eFilterSource.configurators,\r\n valueField: \"id\",\r\n labelField: \"name\",\r\n values: [null],\r\n sticky: true\r\n },\r\n this.getWhereFieldFilter()\r\n );\r\n\r\n filters.pushArray(this.getFiltersFromMeta(meta.QuoteProduct.$name, true));\r\n this.massageFilters(filters);\r\n return filters;\r\n })()\r\n };\r\n }\r\n\r\n public massageFilters(filters: IFilter[]) {\r\n if (!this.agg.$rootScope.company.useDatabaseSearch){\r\n // configured products is a tricky screen since we're searching for quotes, \r\n // but really try to show stuff about products\r\n // so we need to massage the filters to add the nested property syntax\r\n filters.forEach(f => {\r\n if (f.property && !f.property.startsWith(\"products.\")) {\r\n f.property = \"products.\" + f.property;\r\n }\r\n });\r\n }\r\n }\r\n\r\n public postProcessFilters(filters: IFilter[]) {\r\n //don't send the product type filter if they haven't selected one\r\n filters.removeWhere(f => f.property == \"idProduct\" && !f.values.first());\r\n }\r\n\r\n\r\n /**\r\n * the properties of the queried objec that should be returned.\r\n */\r\n public fields(): string[] {\r\n if (this.agg.$rootScope.company.useDatabaseSearch){\r\n return [\r\n meta.QuoteProduct.id.name,\r\n meta.QuoteProduct.name.name,\r\n meta.QuoteProduct.imagePath.name,\r\n meta.QuoteProduct.shortDescription.name,\r\n meta.QuoteProduct.price.name,\r\n meta.QuoteProduct.sku.name,\r\n meta.QuoteProduct.idQuote.name,\r\n meta.QuoteProduct.quote.name,\r\n meta.QuoteProduct.currency.name,\r\n meta.QuoteProduct.modifiedDate.name\r\n ]; \r\n } else {\r\n return [\r\n meta.Quote.id.name,\r\n meta.Quote.name.name,\r\n meta.Quote.description.name,\r\n meta.Quote.customer.name,\r\n meta.Quote.idCustomer.name,\r\n meta.Quote.contact.name,\r\n meta.Quote.idContact.name,\r\n meta.Quote.totalPrice.name,\r\n meta.Quote.state.name,\r\n meta.Quote.createdDate.name,\r\n meta.Quote.modifiedDate.name,\r\n meta.Quote.ownedBy.name,\r\n meta.Quote.owner.name,\r\n meta.Quote.currency.name\r\n ];\r\n }\r\n }\r\n\r\n public nestedFields(): string[] {\r\n if (this.agg.$rootScope.company.useDatabaseSearch){\r\n return []; \r\n } else {\r\n return [\r\n meta.QuoteProduct.id.name,\r\n meta.QuoteProduct.name.name,\r\n meta.QuoteProduct.imagePath.name,\r\n meta.QuoteProduct.shortDescription.name,\r\n meta.QuoteProduct.price.name,\r\n meta.QuoteProduct.sku.name\r\n ];\r\n }\r\n }\r\n\r\n public getNestedPath(): string {\r\n if (this.agg.$rootScope.company.useDatabaseSearch){\r\n return null;\r\n } else {\r\n return \"products\";\r\n }\r\n }\r\n\r\n // public getRawFilter() {\r\n // return { term: { isConfigured: true } };\r\n // }\r\n\r\n public getWhereFieldFilter(): IFilter {\r\n return {\r\n type: eFilterType.fieldValue,\r\n label: \"Where Field\",\r\n fieldName: null,\r\n control: eFilterControl.none,\r\n sourceType: eFilterSource.fields,\r\n values: [null]\r\n };\r\n }\r\n\r\n public getExtraFilters(): IFilter[] {\r\n if (this.agg.$rootScope.company.useDatabaseSearch){\r\n return [\r\n {\r\n property: meta.QuoteProduct.isConfigured.name,\r\n values: [true]\r\n } as IFilter\r\n ];\r\n } else {\r\n return [];\r\n }\r\n \r\n }\r\n}\r\n","import { ICommentsApi } from \"@app/components/kb-comments/kb-comments.component\";\r\nimport { NgView } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { ConfiguratorHelper } from \"@app/helpers/configurator.helper\";\r\nimport { Dirs } from \"@app/helpers/dirs\";\r\nimport { ApiService } from \"@app/services/api.service\";\r\nimport { AuthService, IAuthService } from \"@app/services/auth.service\";\r\nimport { CrudService } from \"@app/services/crud.service\";\r\nimport { IDrawer } from \"@app/services/drawer.service\";\r\nimport { KbService } from \"@app/services/kb.service\";\r\nimport { QuoteService } from \"@app/services/quote.service\";\r\nimport { RuleService } from \"@app/services/rule.service\";\r\nimport { SfdcService } from \"@app/services/sfdc.service\";\r\nimport { StorageService } from \"@app/services/storage.service\";\r\nimport { UploadService } from \"@app/services/upload.service\";\r\nimport { CrudController, ICrudScope } from \"@app/views/crud.view\";\r\nimport { Configurator, ConfiguratorAction, DialogButton, eAlertType, eEnvironment, eFileSource, eFileStatus, eInputDialogType, eRuleType, eValidationType, eViewPermission, eViewType, eWorkflowAction, Field, IAlert, IAllowedAction, IBuildType, ICompany, ICompanyCurrency, IConfiguratorRuleArgs, IConfiguredProduct, IContact, ICustomer, IFieldUploadOptions, IKb3dCallSceneFunctionArgs, IKbFile, IKbUser, InputDialogButton, IPage, IProduct, IProductImageChangeArgs, IQuote, IQuoteFile, IQuoteHeader, IQuoteProduct, IReorderProductsArgs, ISetSceneArgs, ITranslationPackage, IUploadValue, IValidationMessage, IViewPermission, KbObject, KbObjectManager, LayoutConfig, meta, Option, OptionFilter, Page } from \"@models\";\r\nimport { ClientLogger, KPromise } from \"@rules\";\r\nimport { icons, IMessage, Utils } from \"@tools\";\r\nimport { StateParams } from \"@uirouter/angularjs\";\r\nimport * as angular from \"angular\";\r\nimport Big from \"big.js\";\r\nimport * as Q from \"q\";\r\n\r\nexport interface IQuotePermissions {\r\n canModifyName: boolean;\r\n canModifyCustomer: boolean;\r\n canModifyDiscount: boolean;\r\n canModifyProducts: boolean;\r\n canAddAttachments: boolean;\r\n canModifyAttachments: boolean;\r\n canModifyQuoteHeader: boolean;\r\n canModifyCurrency: boolean;\r\n canModifyShipping: boolean;\r\n canViewQuoteHeader: boolean;\r\n canViewDiscount: boolean;\r\n canViewCost: boolean;\r\n canViewPricing: boolean;\r\n canViewCustomer: boolean;\r\n canViewCurrency: boolean;\r\n canViewShipping: boolean;\r\n canReorderProducts: boolean;\r\n canModifyQuoteProductDescription: boolean;\r\n canViewQuoteProductDetails: boolean;\r\n}\r\n\r\nexport interface IQuoteScope extends ICrudScope {\r\n defConfig: Configurator; // the quote header configurator\r\n visiblePages: IPage[];\r\n addProduct: () => void;\r\n deleteProduct: (product: IQuoteProduct) => void;\r\n downloadAttachment: (item: IQuoteFile) => void;\r\n downloadQuoteProductFile: (file: IKbFile) => void;\r\n extNet: (product: IQuoteProduct) => number;\r\n extCost: (product: IQuoteProduct) => number;\r\n margin: (product: IQuoteProduct) => number;\r\n // localPrice: (product: IQuoteProduct) => number;\r\n submit: () => void;\r\n approve: () => void;\r\n reject: () => void;\r\n revise: () => void;\r\n totalCost: () => Big;\r\n totalExtNet: () => Big;\r\n total: () => Big;\r\n\r\n upload: (file, id) => void;\r\n\r\n executeAction: (actionType: string, modifiedProduct?: IQuoteProduct, idCustomAction?: number) => ng.IPromise;\r\n commentListApi: ICommentsApi;\r\n\r\n updateName: () => void;\r\n updateCustomer: () => void;\r\n updateCurrency: () => void;\r\n updateDiscount: () => void;\r\n updateShipping: () => void;\r\n updateProduct: (quoteProduct: IQuoteProduct) => void;\r\n updateProductDescription: (quoteProduct) => void;\r\n\r\n isActiveQuote: () => boolean;\r\n showCopyToThisQuoteBtn: (qp: IQuoteProduct) => boolean;\r\n showCopyToActiveQuoteBtn: (qp: IQuoteProduct) => boolean;\r\n showCopyToNewQuoteBtn: (qp: IQuoteProduct) => boolean;\r\n copyProductToThisQuote: (qp: IQuoteProduct) => ng.IPromise;\r\n copyProductToActiveQuote: (qp: IQuoteProduct) => ng.IPromise;\r\n copyProductToNewQuote: (qp: IQuoteProduct) => ng.IPromise;\r\n\r\n\r\n permissions: IQuotePermissions;\r\n customers: ICustomer[];\r\n contacts: IContact[];\r\n currencies: ICompanyCurrency[];\r\n getCurrencyName: (iso: string) => string;\r\n\r\n isExpanded: (product: IProduct) => boolean;\r\n toggleExpansion: (product: IProduct, expand?: boolean) => void;\r\n\r\n hasFileGenerating: (product: IQuoteProduct) => boolean;\r\n panes: any[];\r\n v: any;\r\n\r\n validationMessages: IValidationMessage[];\r\n validationMessageClicked: (msg: IValidationMessage) => void;\r\n\r\n selectedTab: string;\r\n\r\n inSteelbrick: () => boolean;\r\n searchProducts: (query: string) => ng.IPromise;\r\n submitQuickAdd: (item: IProduct) => void;\r\n binding: { quickAddQuery?: string };\r\n\r\n productSortableOptions: JQueryUI.SortableOptions;\r\n\r\n /*configurator scope properties*/\r\n selectedPageId: string;\r\n runFieldAction: (field: Field) => void;\r\n runAction: (action: ConfiguratorAction) => ng.IPromise;\r\n fieldValueChange: (field: Field) => ng.IPromise;\r\n /** autocomplete field controls asking for updated data */\r\n autoCompleteQuery: (query: string, field: Field) => ng.IPromise;\r\n /** needed for autocompletes that are using the label field to load the initial label to show */\r\n autoCompleteGetLabel: (value: any, field: Field) => ng.IPromise;\r\n showFixedPrice: () => boolean;\r\n\r\n openGoalPriceDialog: (product?: IQuoteProduct) => void;\r\n\r\n translateKbo: (o: KbObject, prop: string) => string;\r\n infiniteScroll: () => void;\r\n productsInView: IQuoteProduct[];\r\n\r\n availableProductBuildTypes: IBuildType[];\r\n productBuildTypes: any;\r\n getAvailableProductBuildTypes: (product: IQuoteProduct) => IBuildType[];\r\n buildProduct: (product: IQuoteProduct, idBuildType: number) => void;\r\n}\r\n\r\nexport interface IRejectDialogScope extends ng.IScope {\r\n model?: IRejectDialogModel;\r\n reasons?: string[];\r\n}\r\nexport interface IRejectDialogModel {\r\n reason?: string;\r\n notes?: string;\r\n}\r\n\r\n// tslint:disable-next-line:no-empty-interface\r\nexport interface IQuoteResolve {\r\n\r\n}\r\n\r\nexport class QuoteHeaderRuleArgs implements IConfiguratorRuleArgs {\r\n constructor(private ctrl: QuoteController) {\r\n this.isMobile = ctrl.$rootScope.windowWidth < Utils.MOBILE_WIDTH;\r\n this.windowWidth = ctrl.$rootScope.windowWidth;\r\n this.windowHeight = ctrl.$rootScope.windowHeight;\r\n }\r\n\r\n public company: ICompany;\r\n public configurator: Configurator;\r\n public layoutConfig: LayoutConfig;\r\n public user: IKbUser;\r\n public kom: KbObjectManager;\r\n public parentKom: KbObjectManager;\r\n public changedField: Field;\r\n public selectedPage: Page;\r\n public environment: string;\r\n public baseUrl: string;\r\n public parameters: any;\r\n public clientLanguage: string;\r\n public logs: ClientLogger;\r\n public quote: IQuote;\r\n public isMobile: boolean;\r\n public windowWidth: number;\r\n public windowHeight: number;\r\n\r\n public getTables(args) {\r\n return new KPromise(args.ids.map(tid => this.ctrl.helper.tableArraysDb[tid]));\r\n }\r\n\r\n public sendMessage(msg: IMessage) {\r\n // send message to embed consumer\r\n Utils.sendMessageToParent({ name: msg.name, data: msg.data });\r\n\r\n this.ctrl.sfdcService.sendMessage(msg);\r\n }\r\n public convertCurrency(obj) {\r\n return this.ctrl.kbService.fxConvertAsync(obj.amount, obj.currencyCode);\r\n }\r\n\r\n public callSafeFunction(obj) {\r\n return this.ctrl.api.safeFunctions.run(obj.safeFunctionId, obj.parameters, this.ctrl.$rootScope.contentTracker);\r\n }\r\n public generateNumber(args) {\r\n return this.ctrl.api.generators.next(args.generatorId, this.ctrl.$rootScope.contentTracker);\r\n }\r\n public selectPage(page) {\r\n this.ctrl.$scope.selectedPageId = page.id;\r\n }\r\n public navigateToElement(elem) {\r\n let page = elem.findAncestor(kbo => kbo instanceof Page) as Page;\r\n if (page && page.visible) {\r\n this.ctrl.$scope.selectedPageId = page.id;\r\n }\r\n }\r\n public nextPage(){\r\n let selectedPage = this.configurator.$manager.get(this.ctrl.$scope.selectedPageId, false);\r\n if (selectedPage){\r\n let index = this.configurator.pages.indexOf(selectedPage);\r\n if (index >= 0 && index < this.configurator.pages.length - 1 ){\r\n this.ctrl.$scope.selectedPageId = this.configurator.pages[index + 1].id;\r\n }\r\n }\r\n }\r\n public backPage(){\r\n let selectedPage = this.configurator.$manager.get(this.ctrl.$scope.selectedPageId, false);\r\n if (selectedPage){\r\n let index = this.configurator.pages.indexOf(selectedPage);\r\n if (index >= 0 && index > 0){\r\n this.ctrl.$scope.selectedPageId = this.configurator.pages[index - 1].id;\r\n }\r\n }\r\n }\r\n public upload() { return this.ctrl.$q.when(null); }\r\n public runSceneAction(name) { return this.ctrl.$q.when(null); }\r\n public callSceneFunction(args: IKb3dCallSceneFunctionArgs){return this.ctrl.$q.when(null);}\r\n public setScene(args: ISetSceneArgs) { return this.ctrl.$q.when(null); }\r\n public runNamingRule() { return this.ctrl.$q.when(null); }\r\n public addNestedConfigurator(idProduct, idParent, name?: string) { return this.ctrl.$q.when(null); }\r\n public copyNestedConfigurator(nested: Configurator | string, idParent, name?: string) { return this.ctrl.$q.when(null); }\r\n public setNumberOfNestedConfigurators(idProduct, idParent, n) { return this.ctrl.$q.when(null); }\r\n public removeNestedConfigurator(nested: Configurator | string) { return this.ctrl.$q.when(null); }\r\n public showPriceDetails() { }\r\n public alert(args: IAlert) { this.ctrl.dialogService.alert(args); }\r\n public getOptionFilterSource(idOptionFilter: string, fromConfigurator?: Configurator) {\r\n fromConfigurator = fromConfigurator || this.configurator;\r\n let f = fromConfigurator.$manager.get(idOptionFilter) as OptionFilter;\r\n return new KPromise(f ? f.$source : []);\r\n }\r\n public setLayoutSetting(id: string, value: any) {}\r\n public getLayoutSetting(id: string) { }\r\n public runConfiguredProduct(cp: IConfiguredProduct) { }\r\n}\r\n\r\n@NgView({\r\n token: Token.QuoteView,\r\n inherit: [Token.CrudView],\r\n dependencies: [\r\n Token.Header,\r\n Token.QuoteService,\r\n Token.SfdcService,\r\n Token.RuleService,\r\n Token.$Filter,\r\n Token.$Timeout,\r\n Token.$Interval,\r\n Token.$Location,\r\n Token.UploadService,\r\n Token.KbService,\r\n Token.StorageService\r\n ],\r\n resolves: [\r\n {\r\n name: \"model\",\r\n dependencies: [\r\n Token.$StateParams,\r\n Token.AuthService,\r\n Token.QuoteService\r\n ],\r\n fn: (\r\n $stateParams: StateParams,\r\n authService: IAuthService,\r\n quoteService: QuoteService\r\n ) => {\r\n return authService.authPromise.then(() => {\r\n if ($stateParams.id) {\r\n return quoteService.getQuoteById($stateParams.id);\r\n } else {\r\n return quoteService.getNewQuote();\r\n }\r\n });\r\n }\r\n },\r\n {\r\n name: \"header\",\r\n dependencies: [\r\n Token.AuthService,\r\n Token.ApiService\r\n ],\r\n fn: (\r\n authService: AuthService,\r\n api: ApiService\r\n ) => {\r\n return authService.authPromise.then(() => {\r\n return api.quoteHeaders.getDefault();\r\n });\r\n }\r\n }\r\n ]\r\n})\r\nexport class QuoteController extends CrudController {\r\n constructor(\r\n public $scope: IQuoteScope,\r\n crudService: CrudService,\r\n model: IQuote,\r\n public header: IQuoteHeader,\r\n public quoteService: QuoteService,\r\n public sfdcService: SfdcService,\r\n public ruleService: RuleService,\r\n public $filter: ng.IFilterService,\r\n public $timeout: ng.ITimeoutService,\r\n public $interval: ng.IIntervalService,\r\n public $location: ng.ILocationService,\r\n public uploadService: UploadService,\r\n public kbService: KbService,\r\n public storageService: StorageService\r\n ) {\r\n\r\n super($scope,\r\n crudService,\r\n model);\r\n\r\n this.bypassUnsavedConfirmation = !!model.idWorkflow;\r\n\r\n this.drawerService.setHelpUrl(\"Quotes\");\r\n this.drawerService.pageTitle = this.$scope.model ? this.$scope.model.name : loc.newquote;\r\n this.drawerService.pageType = loc.quote_title;\r\n this.drawerService.pageIcon = icons.quote;\r\n\r\n $scope.v = {};\r\n $scope.customers = [];\r\n $scope.contacts = [];\r\n $scope.currencies = [];\r\n $scope.validationMessages = [];\r\n $scope.binding = {};\r\n $scope.selectedTab = \"tab_basic\";\r\n $scope.productsInView = [];\r\n $scope.productBuildTypes = {};\r\n /*$rootScope.$on(events.loginSuccessful, () =>\r\n {\r\n this.subscribe().finally(() =>\r\n {\r\n if (this.submitQuotePending) {\r\n this.submitQuotePending = false;\r\n this.dialogService.confirm(\"Would you like to continue submitting your quote?\", () =>\r\n {\r\n this.submit();\r\n });\r\n }\r\n });\r\n });*/\r\n\r\n let thisCtrl = this;\r\n $scope.upload = function(file, field) {\r\n let uploadOptions = {\r\n convertPdfToImage: field.convertUploadPdfToImage\r\n } as IFieldUploadOptions;\r\n return thisCtrl.uploadService.uploadQuoteFile(file, uploadOptions).then(uuid => {\r\n let uploadValue = field.value as IUploadValue;\r\n uploadValue.path = uuid;\r\n // clear the asset id in case there was an old file there that was just \r\n // replaced to make sure the new file is uploaded to the scene\r\n uploadValue.assetId = null;\r\n \r\n });\r\n };\r\n\r\n let viewType = this.$state.current.data.viewType;\r\n\r\n if ($scope.model) {\r\n this.deleteMsg = loc.msg_deleterecord.format(loc.quote_title, $scope.model.name);\r\n }\r\n\r\n this.onRelationshipEdited(\"Files\", m => {\r\n this.setUpdatedModelInternal(m, false);\r\n });\r\n\r\n if (viewType == eViewType.new) {\r\n let idCategory = this.$location.search().idcategory;\r\n model = $scope.model = quoteService.getNewQuote();\r\n\r\n if (this.sfdcService.record() && this.sfdcService.record().Name) {\r\n $scope.model.name = this.sfdcService.record().Name;\r\n }\r\n }\r\n\r\n\r\n if (this.$rootScope.isSfdc && !this.$rootScope.isSfdcCpq) {\r\n quoteService.quote = this.$scope.model;\r\n }\r\n\r\n\r\n $scope.updateName = () => {\r\n if ($scope.model.state) {\r\n if (this.validate() || this.$rootScope.context.companySettings.allowInvalidQuotesInWorkflow) {\r\n $scope.executeAction(eWorkflowAction.modifyName);\r\n }\r\n else {\r\n this.promptUserToFixErrors();\r\n this.revertToClean();\r\n }\r\n }\r\n }\r\n\r\n $scope.updateCurrency = () => {\r\n if ($scope.model.state) {\r\n if (this.validate() || this.$rootScope.context.companySettings.allowInvalidQuotesInWorkflow) {\r\n $scope.executeAction(eWorkflowAction.modifyCurrency);\r\n } else if ($scope.model.state) {\r\n this.promptUserToFixErrors();\r\n this.revertToClean();\r\n }\r\n }\r\n };\r\n\r\n $scope.updateCustomer = () => {\r\n // update the customer name for display (when the kbAtom is not active)\r\n let customer = $scope.customers.find(c => c.id == $scope.model.idCustomer);\r\n $scope.model.customer = customer ? customer.name : null;\r\n let contact = $scope.contacts.find(c => c.id == $scope.model.idContact);\r\n $scope.model.contact = contact ? contact.name : null;\r\n\r\n if ($scope.model.state) {\r\n if (this.validate() || this.$rootScope.context.companySettings.allowInvalidQuotesInWorkflow) {\r\n $scope.executeAction(eWorkflowAction.modifyCustomer);\r\n } else if ($scope.model.state) {\r\n this.promptUserToFixErrors();\r\n this.revertToClean();\r\n }\r\n }\r\n };\r\n\r\n $scope.updateDiscount = () => {\r\n if ($scope.model.state) {\r\n if (this.validate() || this.$rootScope.context.companySettings.allowInvalidQuotesInWorkflow) {\r\n $scope.executeAction(eWorkflowAction.modifyDiscount);\r\n } else if ($scope.model.state) {\r\n this.promptUserToFixErrors();\r\n this.revertToClean();\r\n }\r\n }\r\n };\r\n\r\n $scope.updateShipping = () => {\r\n if ($scope.model.state) {\r\n if (this.validate() || this.$rootScope.context.companySettings.allowInvalidQuotesInWorkflow) {\r\n $scope.executeAction(eWorkflowAction.modifyShipping);\r\n } else if ($scope.model.state) {\r\n this.promptUserToFixErrors();\r\n this.revertToClean();\r\n }\r\n }\r\n };\r\n\r\n $scope.updateProduct = quoteProduct => {\r\n if (this.validate() || this.$rootScope.context.companySettings.allowInvalidQuotesInWorkflow) {\r\n if ($scope.model.idWorkflow || quoteProduct.requiresUpdate) {\r\n // we are in a workflow so we need to run the action OR we need to update\r\n // the product to re - run it's pricing rule (if it uses the qtyInQuote variable)\r\n return $scope.executeAction(eWorkflowAction.modifyProducts, quoteProduct);\r\n }\r\n } else if ($scope.model.state) {\r\n this.promptUserToFixErrors();\r\n this.revertToClean();\r\n }\r\n };\r\n\r\n $scope.updateProductDescription = quoteProduct => {\r\n if (this.validate()) {\r\n if ($scope.model.idWorkflow || quoteProduct.requiresUpdate) {\r\n // we are in a workflow so we need to run the action OR we need to update the product\r\n // to re - run it's pricing rule (if it uses the qtyInQuote variable)\r\n return $scope.executeAction(eWorkflowAction.modifyQuoteProductDescription, quoteProduct);\r\n }\r\n }\r\n };\r\n\r\n if (!$scope.model.discountPercentage) $scope.model.discountPercentage = 0;\r\n\r\n\r\n $scope.getAvailableProductBuildTypes = (product: IQuoteProduct) => {\r\n let result = [];\r\n\r\n if (product.isConfigured && this.$scope.productBuildTypes[product.idProduct]) {\r\n result = $scope.availableProductBuildTypes.filter(b => this.$scope.productBuildTypes[product.idProduct].contains(b.id));\r\n }\r\n\r\n return result;\r\n }\r\n\r\n $scope.buildProduct = (product: IQuoteProduct, idBuildType: number) => {\r\n this.api.quotes.buildQuoteProduct(this.$scope.model.id, product.id, idBuildType).then(q => {\r\n this.handleActionResponse(q, eWorkflowAction.buildQuoteProduct);\r\n this.dialogService.alert({\r\n type: eAlertType.success,\r\n persist: false,\r\n msg: loc.quoteproductbuilding\r\n });\r\n });\r\n }\r\n\r\n $scope.commentListApi = {\r\n refresh: () => {\r\n\r\n }\r\n };\r\n\r\n $scope.downloadQuoteProductFile = (file: IKbFile) => {\r\n this.$window.open(\"/api/quotes/productfile/download/\" + file.id, \"_blank\");\r\n };\r\n\r\n $scope.addProduct = () => {\r\n this.validate();\r\n if (!this.$scope.model.name) return;\r\n // save the current quote\r\n quoteService.quote = $scope.model;\r\n $scope.executeAction(eWorkflowAction.save).then(() => {\r\n this.bypassUnsavedConfirmation = true;\r\n this.$state.go(\"kb.products\");\r\n });\r\n };\r\n\r\n let expandedProducts = {};\r\n\r\n $scope.isExpanded = product => {\r\n return expandedProducts[product.id];\r\n };\r\n\r\n $scope.toggleExpansion = (product, expand) => {\r\n if (expand == null) {\r\n expandedProducts[product.id] = !expandedProducts[product.id];\r\n } else {\r\n expandedProducts[product.id] = expand;\r\n }\r\n };\r\n\r\n $scope.downloadAttachment = (item: IQuoteFile) => {\r\n if (item.source == eFileSource.media) {\r\n window.open(storageService.getMediaUrl(item.filePath));\r\n } else {\r\n window.open(\"api/quotes/file/download/\" + item.id, \"_blank\");\r\n }\r\n };\r\n\r\n $scope.hasFileGenerating = product => {\r\n return product.files && product.files.some(f => f.status == eFileStatus.generating);\r\n };\r\n\r\n $scope.deleteProduct = (product: IQuoteProduct) => {\r\n this.dialogService.dialog({\r\n content: loc.msg_deletequoteproduct.format(product.name),\r\n buttons: [\r\n new DialogButton(loc.ok, icons.success, args => {\r\n let promise: ng.IPromise = this.$q.when(true);\r\n if (!this.$scope.model.idWorkflow) {\r\n promise = this.$scope.executeAction(eWorkflowAction.save);\r\n }\r\n return promise.then(() => {\r\n return this.api.quotes.deleteQuoteProduct($scope.model.id, product, this.$rootScope.contentTracker).then(r => {\r\n this.handleActionResponse(r, eWorkflowAction.modifyProducts);\r\n });\r\n });\r\n }),\r\n new DialogButton(loc.cancel, icons.cancel, args => {\r\n\r\n })\r\n ]\r\n });\r\n };\r\n\r\n $scope.isActiveQuote = () => {\r\n return quoteService.quote != null && $scope.model.id == quoteService.quote.id;\r\n };\r\n\r\n $scope.showCopyToActiveQuoteBtn = (qp) => {\r\n /** only show this 'copy to active quote' button if we are not in the active quote, and the active quote allows modifying products */\r\n return (\r\n qp.isConfigured\r\n && !$scope.isActiveQuote() //this quote is not the active quote\r\n && quoteService.quote\r\n && quoteService.canModifyProductsOfQuote(quoteService.quote)\r\n && !this.$rootScope.isSfdc //this should never happen in CRM integration\r\n );\r\n };\r\n\r\n $scope.showCopyToThisQuoteBtn = (qp) => {\r\n /** only show 'copy to this quote' button if this quote has modify products permissions */\r\n return (\r\n qp.isConfigured\r\n && $scope.permissions.canModifyProducts\r\n );\r\n };\r\n\r\n $scope.showCopyToNewQuoteBtn = (qp) => {\r\n return qp.isConfigured && !this.$rootScope.isSfdc; //creating a new quote in this way would break the CRM integration\r\n }\r\n\r\n $scope.copyProductToThisQuote = (qp) => {\r\n this.quoteService.quote = this.$scope.model; //make this the active quote\r\n let copyProduct = () => {\r\n return quoteService.copyProductToActiveQuote(qp.id).then(r => {\r\n if (quoteService.quote && quoteService.quote.id == $scope.model.id) {\r\n this.$state.reload();\r\n } else {\r\n quoteService.goToQuote();\r\n }\r\n });\r\n };\r\n if (!this.$scope.model.idWorkflow && !this.modelIsClean()) {\r\n return this.$scope.executeAction(eWorkflowAction.save).then(copyProduct);\r\n }\r\n else {\r\n return copyProduct();\r\n }\r\n };\r\n\r\n $scope.copyProductToActiveQuote = (qp) => {\r\n return quoteService.copyProductToActiveQuote(qp.id).then(r => {\r\n if (quoteService.quote && quoteService.quote.id == $scope.model.id) {\r\n this.$state.reload();\r\n } else {\r\n quoteService.goToQuote();\r\n }\r\n });\r\n };\r\n\r\n $scope.copyProductToNewQuote = (qp) => {\r\n return quoteService.copyProductToNewQuote(qp.id).then(r => {\r\n quoteService.goToQuote();\r\n });\r\n };\r\n\r\n \r\n\r\n // $scope.delete = () => {\r\n // return this.delete().then(() => {\r\n // // if the quote we're deleting is the active quote, clear it out of the quoteservice\r\n // if (quoteService.quote && quoteService.quote.id == $scope.model.id) {\r\n // quoteService.quote = undefined;\r\n // }\r\n // });\r\n // };\r\n\r\n $scope.extNet = product => {\r\n let discount = product.discountPercentage || 0;\r\n let volumeDiscount = 0;\r\n let volumeDiscounts = product.volumeDiscounts.sort((vd1, vd2) => vd1.qty - vd2.qty);\r\n for (var key in volumeDiscounts) {\r\n let vd = volumeDiscounts[key];\r\n if (vd.qty > product.qty) break;\r\n volumeDiscount = vd.disc;\r\n }\r\n let nonfixed = Big(product.price).minus(Big(product.fixedPrice)).times(Big(product.qty));\r\n let ext = nonfixed.plus(Big(product.fixedPrice));\r\n let extNet: any = ext.minus(ext.times(Big(discount).div(100))).minus(ext.times(Big(volumeDiscount).div(100)));\r\n\r\n return extNet;\r\n };\r\n\r\n $scope.margin = product => {\r\n return $scope.extNet(product) - $scope.extCost(product);\r\n }\r\n\r\n $scope.extCost = product => {\r\n let extCost: any = Big(product.cost)\r\n .minus(Big(product.fixedCost))\r\n .times(product.qty)\r\n .plus(Big(product.fixedCost));\r\n return extCost;\r\n };\r\n\r\n let sum = (mapFn: (product: IQuoteProduct) => number): Big => {\r\n let products = $scope.model.products;\r\n\r\n let total = products.reduce((previousValue: Big, currentValue: IQuoteProduct, index: number) => {\r\n let product = products[index];\r\n let propValue = mapFn(product);\r\n return previousValue.plus(Big(propValue));\r\n }, Big(0));\r\n\r\n return total as Big;\r\n };\r\n\r\n $scope.totalCost = () => {\r\n return sum(product => $scope.extCost(product));\r\n };\r\n\r\n $scope.totalExtNet = () => {\r\n return sum(product => $scope.extNet(product));\r\n };\r\n\r\n $scope.total = () => {\r\n let extNet = $scope.totalExtNet();\r\n let discount = $scope.model.discountPercentage || 0;\r\n let shipping = $scope.model.shipping || 0;\r\n return extNet.minus(extNet.times(Big(discount).div(100))).plus(Big(shipping));\r\n };\r\n\r\n $scope.showFixedPrice = () => {\r\n return $scope.model.products.some(p => p.fixedPrice != 0);\r\n };\r\n\r\n $scope.openGoalPriceDialog = (product?: IQuoteProduct) => {\r\n let value = Math.round(Number(product ? product.price : $scope.total()) * 100) / 100;\r\n let undiscountedValue = (product ? product.price : $scope.totalExtNet());\r\n this.dialogService.input({\r\n inputType: eInputDialogType.text,\r\n value: value,\r\n msg: \"Please enter the desired goal price for \" + (product ? \"each \" + product.name : \"this quote\") + \".\",\r\n buttons: [\r\n new InputDialogButton(loc.ok, icons.success, args => {\r\n let discount = Number(Big(args.value).div(undiscountedValue));\r\n discount = Math.round((1 - discount) * 10000) / 100;\r\n if (product) {\r\n product.discountPercentage = discount;\r\n }\r\n else {\r\n $scope.model.discountPercentage = discount;\r\n }\r\n }),\r\n new InputDialogButton(loc.cancel, icons.cancel, args => {\r\n })\r\n ]\r\n });\r\n }\r\n\r\n $scope.panes = [\r\n { title: \"General\", content: \"general\", disabled: false },\r\n { title: \"Comments\", content: \"comments\", disabled: false },\r\n { title: \"History\", content: \"history\", disabled: false }];\r\n\r\n $scope.inSteelbrick = () => {\r\n return (this.sfdcService.record() && this.sfdcService.record().attributes.type == \"SBQQ__Quote__c\");\r\n };\r\n\r\n $scope.searchProducts = (query: string): ng.IPromise => {\r\n if (!query) {\r\n return Q.resolve([]);\r\n }\r\n return this.api.products.searchByCategory({\r\n query,\r\n skip: 0,\r\n take: 11,\r\n filters: [\r\n {\r\n property: meta.Product.isConfigured.name,\r\n values: [false]\r\n }\r\n ]\r\n });\r\n };\r\n\r\n $scope.submitQuickAdd = (item: IProduct) => {\r\n if (!item) return;\r\n this.$scope.binding.quickAddQuery = \"\";\r\n\r\n let addProduct = () => {\r\n this.quoteService.quote = this.$scope.model;\r\n this.quoteService.addProduct({\r\n qty: 1,\r\n configuredProduct: null,\r\n idProduct: item.id,\r\n addLocally: false\r\n }).then(() => {\r\n this.setUpdatedModelInternal(this.quoteService.quote, false);\r\n });\r\n };\r\n\r\n if (this.$scope.model.name) {\r\n if (this.$scope.model.id) {\r\n addProduct();\r\n } else {\r\n this.$scope.executeAction(eWorkflowAction.save).then(addProduct);\r\n }\r\n }\r\n };\r\n\r\n $scope.productSortableOptions = {\r\n stop: (e, ui) => {\r\n if (this.$scope.permissions.canReorderProducts && this.validate()) {\r\n // set product order\r\n for (let i = 0; i < $scope.model.products.length; i++) {\r\n $scope.model.products[i].order = i;\r\n }\r\n //reset the products in view\r\n this.$scope.productsInView = [];\r\n this.$scope.infiniteScroll();\r\n if ($scope.model.idWorkflow) { // we are in a workflow so we need to run the action\r\n this.$timeout(() => {\r\n return $scope.executeAction(eWorkflowAction.reorderProducts);\r\n }, 0);\r\n }\r\n } else {\r\n // $(\".kb-quote__ops\").sortable(\"cancel\");\r\n }\r\n },\r\n disabled: true,\r\n handle: \".kb-grip\"\r\n };\r\n\r\n $scope.executeAction = (\r\n actionType: string,\r\n modifiedProduct: IQuoteProduct = null,\r\n idCustomAction: number = 0\r\n ): ng.IPromise => {\r\n let data;\r\n let url = \"/api/quotes/\" + actionType;\r\n let method = \"POST\";\r\n let getDataDeferred = this.$q.defer();\r\n\r\n if (!this.validate() && !this.$rootScope.context.companySettings.allowInvalidQuotesInWorkflow &&\r\n actionType != eWorkflowAction.reject &&\r\n actionType != eWorkflowAction.save &&\r\n actionType != eWorkflowAction.deleter) {\r\n\r\n this.promptUserToFixErrors();\r\n return;\r\n }\r\n\r\n if (!$scope.model.externalId &&\r\n this.sfdcService.record() &&\r\n this.sfdcService.record().attributes.type == \"KBMAX__Quote__c\"\r\n ) { // add the externalId to the quote\r\n $scope.model.externalId = this.sfdcService.record().Id;\r\n }\r\n $scope.model.headerValues = $scope.defConfig.getConfiguredProduct();\r\n \r\n\r\n if (actionType == eWorkflowAction.save) {\r\n data = $scope.model;\r\n getDataDeferred.resolve();\r\n } else if (actionType == eWorkflowAction.custom) {\r\n data = { idQuote: $scope.model.id, idCustomAction };\r\n getDataDeferred.resolve();\r\n } else if (actionType == eWorkflowAction.reject) {\r\n // build up a scope to drive the dialog ui\r\n let dialogScope: IRejectDialogScope = $scope.$new(true);\r\n dialogScope.model = {\r\n reason: loc.other,\r\n notes: \"\"\r\n };\r\n dialogScope.reasons = $scope.model.rejectedReasons;\r\n\r\n this.dialogService.dialog({\r\n template: Dirs.view(\"dialog-reject\"),\r\n scope: dialogScope,\r\n buttons: [\r\n new DialogButton(loc.continuer, icons.success, args => {\r\n data = {\r\n quote: $scope.model,\r\n reason: dialogScope.model.reason,\r\n notes: dialogScope.model.notes\r\n };\r\n getDataDeferred.resolve();\r\n }),\r\n new DialogButton(loc.cancel, icons.cancel, args => { })\r\n ]\r\n });\r\n } else if (actionType == eWorkflowAction.modifyProducts) {\r\n url = \"/api/quotes/\" + this.$scope.model.id + \"/product/\" + modifiedProduct.id;\r\n method = \"PUT\";\r\n data = modifiedProduct;\r\n getDataDeferred.resolve();\r\n } else if (actionType == eWorkflowAction.modifyQuoteProductDescription) {\r\n url = \"/api/quotes/\" + this.$scope.model.id + \"/product/\" + modifiedProduct.id + \"/description\";\r\n method = \"PUT\";\r\n data = modifiedProduct;\r\n getDataDeferred.resolve();\r\n } else if (actionType == eWorkflowAction.reorderProducts) {\r\n url = \"/api/quotes/reorderproducts\";\r\n method = \"POST\";\r\n data = {\r\n id: this.$scope.model.id,\r\n products: this.$scope.model.products.map(qp => {\r\n return { id: qp.id, order: qp.order };\r\n })\r\n } as IReorderProductsArgs;\r\n getDataDeferred.resolve();\r\n } else {\r\n data = $scope.model;\r\n getDataDeferred.resolve();\r\n }\r\n\r\n return getDataDeferred.promise.then(() => {\r\n return this.$http({\r\n method,\r\n url,\r\n data,\r\n tracker: this.$rootScope.contentTracker\r\n }).then(response => {\r\n return this.handleActionResponse(response.data, actionType);\r\n });\r\n });\r\n };\r\n\r\n $scope.runFieldAction = field => {\r\n return this.helper.runRuleContainerAsync(field)\r\n .then(() => this.runRuleCycleUnit(field.$parentConfigurator, null))\r\n .then(() => {\r\n if (this.$scope.model.idWorkflow) {\r\n return this.$scope.executeAction(eWorkflowAction.modifyQuoteHeader);\r\n }\r\n });\r\n };\r\n\r\n $scope.runAction = action => {\r\n return this.helper.runRuleContainerAsync(action)\r\n .then(() => this.runRuleCycleUnit(action.$parentConfigurator, null));\r\n };\r\n $scope.fieldValueChange = field => {\r\n return this.helper.runRuleContainerAsync(field)\r\n .then(() => this.runRuleCycleUnit(field.$parentConfigurator, field))\r\n .then(() => {\r\n if (this.$scope.model.idWorkflow) {\r\n return this.$scope.executeAction(eWorkflowAction.modifyQuoteHeader);\r\n }\r\n });\r\n };\r\n $scope.autoCompleteQuery = (query, field) => {\r\n return this.helper.autoCompleteQuery(query, field);\r\n };\r\n $scope.autoCompleteGetLabel = (value, field) => {\r\n return this.helper.autoCompleteGetLabel(value, field);\r\n };\r\n $scope.getCurrencyName = iso => {\r\n let cc = $scope.currencies.find(c => c.currency.isEqual(iso));\r\n return cc ? `${cc.name} (${cc.currency})` : iso;\r\n };\r\n $scope.validationMessageClicked = msg => {\r\n\r\n };\r\n $scope.translateKbo = (o, prop) => {\r\n if (o) {\r\n if (this.$rootScope.companySettings.defaultLanguage != this.$rootScope.clientLanguage) {\r\n if (this.translationDb.hasOwnProperty(o.id) && this.translationDb[o.id].hasOwnProperty(prop)) {\r\n return this.translationDb[o.id][prop];\r\n }\r\n }\r\n let realProp = prop == \"name\" ? \"$label\" : prop;\r\n return o[realProp];\r\n }\r\n return \"\";\r\n };\r\n\r\n $scope.infiniteScroll = () => {\r\n let pageSize = 30;\r\n let totalCount = $scope.model.products.length;\r\n let currCount = $scope.productsInView.length;\r\n if (totalCount > currCount) {\r\n $scope.productsInView.pushArray($scope.model.products.slice(currCount, currCount + pageSize));\r\n }\r\n };\r\n\r\n this.refreshPermissions();\r\n\r\n this.helper = new ConfiguratorHelper({\r\n $http: this.$http,\r\n $q: this.$q,\r\n api: this.api,\r\n dialogService: this.dialogService,\r\n ruleService: this.ruleService,\r\n tracker: this.$rootScope.contentTracker,\r\n $rootScope: this.$rootScope,\r\n getRuleArgs: (c, f) => this.getRuleArgs(c, f),\r\n showErrors: () => (this.$rootScope.environment != eEnvironment.prod)\r\n });\r\n\r\n this.refreshDrawers();\r\n\r\n this.setupQuoteHeader();\r\n\r\n this.validate();\r\n\r\n this.startConfigurator();\r\n\r\n $scope.$on(\"$destroy\", () => {\r\n this.stopValidationTimer();\r\n });\r\n\r\n // currencies\r\n this.api.currencies.companyOptions().then(r => {\r\n $scope.currencies = r;\r\n });\r\n\r\n let updateCustomers = () => {\r\n this.api.customers.search({\r\n fields: [\"id\", \"name\"],\r\n sortField: \"name\"\r\n }).then(r => $scope.customers = r);\r\n };\r\n\r\n let updateContacts = () => {\r\n if ($scope.model.idCustomer) {\r\n this.api.contacts.search({\r\n filters: [{\r\n property: \"idCustomer\",\r\n values: [$scope.model.idCustomer]\r\n }]\r\n }).then(r => $scope.contacts = r);\r\n } else {\r\n $scope.contacts.clear();\r\n }\r\n };\r\n\r\n\r\n\r\n if (this.$rootScope.companySettings.enableCustomersAndContacts && (this.$scope.permissions.canViewCustomer || this.$scope.permissions.canModifyCustomer)) {\r\n updateCustomers();\r\n }\r\n\r\n $scope.$watch(\"model.idCustomer\", (newValue, oldValue) => {\r\n updateContacts();\r\n });\r\n\r\n this.$scope.infiniteScroll(); //fill in first set of products\r\n this.startValidationTimer();\r\n\r\n if (this.$scope.isNew && this.$rootScope.isSfdc && !this.$rootScope.isSfdcCpq) {\r\n let canvasParams = this.$rootScope.context.sfdcCanvasRequest.context.environment.parameters;\r\n if (canvasParams.autoSubmit != null && (canvasParams.autoSubmit == true || canvasParams.autoSubmit.isEqual(\"true\"))) {\r\n this.submit();\r\n } else {\r\n this.$scope.executeAction(eWorkflowAction.save);\r\n }\r\n }\r\n }\r\n\r\n private submitQuotePending: boolean;\r\n public helper: ConfiguratorHelper;\r\n public translationDb: { [id: string]: ITranslationPackage } = {};\r\n private _stopValidationTimer: ng.IPromise;\r\n public productImageChange: (args: IProductImageChangeArgs) => void;\r\n\r\n public client(api: ApiService) {\r\n return api.quotes;\r\n }\r\n\r\n public onSuccess() {\r\n this.$state.go(\"kb.quoteEdit\", { id: this.$scope.model.id });\r\n this.drawerService.pageTitle = this.$scope.model.name;\r\n // this.registerWebSocket();\r\n }\r\n\r\n public onDelete() {\r\n // if the quote we're deleting is the active quote, clear it out of the quoteservice\r\n if (this.quoteService.quote && this.quoteService.quote.id == this.$scope.model.id) {\r\n this.quoteService.quote = undefined;\r\n }\r\n this.$state.go(\"kb.quotes\");\r\n }\r\n\r\n public webSocketEntityType() {\r\n return \"Quote\";\r\n }\r\n\r\n public subscribe() {\r\n super.subscribe();\r\n this.signalrService.on(\"productImageChange\", this.productImageChange = (args: IProductImageChangeArgs) => {\r\n if (args.idQuote == this.$scope.model.id) {\r\n this.$timeout(() => {\r\n let product = this.$scope.model.products.find(p => p.id == args.idQuoteProduct);\r\n if (product) product.imagePath = args.imagePath;\r\n }, 0);\r\n }\r\n });\r\n }\r\n\r\n public unsubscribe() {\r\n super.unsubscribe();\r\n this.signalrService.off(\"productImageChange\", this.productImageChange);\r\n }\r\n\r\n protected setUpdatedModel(model: IQuote) {\r\n this.setUpdatedModelInternal(model);\r\n }\r\n\r\n protected setUpdatedModelInternal(model: IQuote, refreshComments: boolean = true) {\r\n this.$scope.model = model;\r\n this.refreshDrawers();\r\n // refresh the comments as sometimes they are added server-side (like for rejection reasons)\r\n if (refreshComments)\r\n this.$scope.commentListApi.refresh();\r\n this.refreshPermissions();\r\n this.$scope.productsInView = [];\r\n this.$scope.infiniteScroll();\r\n }\r\n\r\n protected setupQuoteHeader() {\r\n let configurator = new Configurator(new KbObjectManager(), this.header.configurator);\r\n configurator.$running = true;\r\n if (this.$scope.isEdit && this.$scope.model.headerValues) {\r\n configurator.runConfiguredProduct(this.$scope.model.headerValues, null);\r\n }\r\n\r\n this.$scope.defConfig = configurator;\r\n this.$scope.visiblePages = this.$scope.defConfig.pages.filter(p => p.visible);\r\n\r\n // setup translationDb\r\n let trans = this.header.translations.first();\r\n if (trans) {\r\n Object.keys(trans.data.objects).forEach(key => {\r\n this.translationDb[key] = trans.data.objects[key];\r\n });\r\n }\r\n }\r\n\r\n private refreshDrawers() {\r\n // TODO: This doesn't work for some reason.\r\n // if (this.$state.current.controller != kb.quoteController) return;\r\n this.drawerService.drawers.clear();\r\n this.$scope.availableProductBuildTypes = [];\r\n\r\n if (this.$scope.model.idWorkflow > 0) {\r\n let actions = this.$scope.model.allowedActions;\r\n let hasBuildProductAction = false;\r\n if (actions) {\r\n angular.forEach(actions, (action: IAllowedAction) => {\r\n if (action.type == eWorkflowAction.modifyCustomer ||\r\n action.type == eWorkflowAction.modifyDiscount ||\r\n action.type == eWorkflowAction.modifyName ||\r\n action.type == eWorkflowAction.addAttachments ||\r\n action.type == eWorkflowAction.modifyAttachments ||\r\n action.type == eWorkflowAction.completeBuild ||\r\n action.type == eWorkflowAction.failBuild ||\r\n action.type == eWorkflowAction.modifyQuoteHeader ||\r\n action.type == eWorkflowAction.modifyCurrency ||\r\n action.type == eWorkflowAction.reorderProducts ||\r\n action.type == eWorkflowAction.modifyQuoteProductDescription ||\r\n action.type == eWorkflowAction.modifyShipping) {\r\n // do nothing\r\n } else if (action.type == eWorkflowAction.modifyProducts) {\r\n // unshift so addProducts is always at the left\r\n this.drawerService.drawers.unshift({\r\n icon: icons.products,\r\n label: loc.addproduct,\r\n visible: true,\r\n command: () => {\r\n // set the active quote\r\n this.quoteService.quote = this.$scope.model;\r\n this.$state.go(\"kb.products\");\r\n }\r\n });\r\n } else if (action.type == eWorkflowAction.buildQuoteProduct) {\r\n this.$scope.availableProductBuildTypes.push(action.buildType);\r\n hasBuildProductAction = true;\r\n } else {\r\n let icon = action.type == eWorkflowAction.custom ? action.icon : icons[action.type];\r\n let actionName = action.type == eWorkflowAction.custom ?\r\n action.name\r\n : loc[action.type] || action.type;\r\n this.drawerService.addDrawer(icon, actionName, () => {\r\n this.$scope.executeAction(action.type, null, action.idCustomAction);\r\n });\r\n }\r\n });\r\n\r\n if (hasBuildProductAction) {\r\n this.api.quotes.getProductBuildTypes(this.$scope.model.id).then((result) => {\r\n result.value.forEach(pbt => {\r\n this.$scope.productBuildTypes[pbt.idProduct] = pbt.idBuildTypes;\r\n });\r\n });\r\n }\r\n }\r\n } else {\r\n if (this.$scope.isEdit) {\r\n let drAddProduct = this.drawerService.addDrawer(icons.products, loc.addproduct, this.$scope.addProduct);\r\n if (!this.$rootScope.isSfdc) {\r\n let drDelete = this.drawerService.addDrawer(icons.deleter, loc.deleter, this.$scope.delete);\r\n }\r\n }\r\n let drSave = this.drawerService.addDrawer(icons.save, loc.save, () => {\r\n this.validate();\r\n if (this.$scope.model.name) {\r\n this.$scope.executeAction(eWorkflowAction.save).then(() => {\r\n if (this.$state.current.data.viewType == eViewType.new &&\r\n this.$rootScope.user.id == AuthService.ANONYMOUS_USER_ID\r\n ) {\r\n // Anonymous users need to immediately activate this newly saved quote, \r\n // since otherwise they'll not have access to it ever again.\r\n this.quoteService.quote = this.$scope.model;\r\n }\r\n });\r\n }\r\n });\r\n let drSubmit = this.drawerService.addDrawer(icons.play, loc.submit, () => {\r\n drSubmit.disabled = true;\r\n this.submit();\r\n });\r\n }\r\n\r\n let last = this.drawerService.drawers.last();\r\n if (last) last.endGroup = true;\r\n\r\n if (this.$rootScope.isSfdc && !this.$rootScope.isSfdcCpq && this.$scope.model.externalId) {\r\n let drPrimary: IDrawer;\r\n if (this.$scope.isEdit &&\r\n this.sfdcService.record().KBMAX__Opportunity__c &&\r\n !this.sfdcService.record().KBMAX__Primary__c\r\n ) {\r\n drPrimary = this.drawerService.addDrawer(icons.approve, \"Make Primary\", () => {\r\n let p = this.sfdcService.makePrimaryQuote(this.$scope.model);\r\n this.dialogService.alert({\r\n promise: p,\r\n msg: \"Setting \" + this.$scope.model.name + \" as primary quote\",\r\n successMsg: this.$scope.model.name +\r\n \" has successfully been made the primary quote of the opportunity\"\r\n });\r\n this.refreshDrawers();\r\n });\r\n drPrimary.startGroup = true;\r\n }\r\n // add an sfdc 'out' button to take us back to the sfdc quote (or opportunity) \r\n let drDone = this.drawerService.addDrawer(icons.success, loc.done, () => {\r\n /*if sfdc passed in a \"navigateTo\" id parameter, then we go there on done\r\n if not, then we go to the sfdc quote object. You can use this for example\r\n to go back to the opportunity instead of the quote */\r\n let canvasParams = this.$rootScope.context.sfdcCanvasRequest.context.environment.parameters;\r\n if (canvasParams.navigateTo != null) {\r\n this.sfdcService.navigateToObject(canvasParams.navigateTo);\r\n } else {\r\n this.sfdcService.navigateToObject(this.$scope.model.externalId);\r\n }\r\n \r\n });\r\n if (!drPrimary) drDone.startGroup = true;\r\n } else if (this.$rootScope.isSfdc && this.$scope.inSteelbrick()) {\r\n // add an sfdc 'out' button to take us back to the sfdc quote (or opportunity) \r\n let drDone = this.drawerService.addDrawer(icons.success, loc.done, () => {\r\n this.sfdcService.sendMessage({ name: \"goToSteelbrickQuote\", data: this.sfdcService.record().Id });\r\n });\r\n }\r\n }\r\n\r\n private canUserPerformAction(actionType: string) {\r\n return this.$scope.model.allowedActions.some((a: IAllowedAction) => a.type == actionType);\r\n }\r\n\r\n public refreshPermissions() {\r\n if (this.$scope.model.idWorkflow) {\r\n this.$scope.permissions = {\r\n canModifyName: this.canUserPerformAction(eWorkflowAction.modifyName),\r\n canModifyCustomer: this.canUserPerformAction(eWorkflowAction.modifyCustomer),\r\n canModifyDiscount: this.canUserPerformAction(eWorkflowAction.modifyDiscount),\r\n canModifyProducts: this.canUserPerformAction(eWorkflowAction.modifyProducts),\r\n canAddAttachments: this.canUserPerformAction(eWorkflowAction.addAttachments),\r\n canModifyQuoteHeader: this.canUserPerformAction(eWorkflowAction.modifyQuoteHeader),\r\n canModifyAttachments: this.canUserPerformAction(eWorkflowAction.modifyAttachments),\r\n canModifyCurrency: this.canUserPerformAction(eWorkflowAction.modifyCurrency),\r\n canModifyShipping: this.canUserPerformAction(eWorkflowAction.modifyShipping),\r\n canReorderProducts: this.canUserPerformAction(eWorkflowAction.reorderProducts),\r\n canViewQuoteHeader: this.$scope.model.userViewPermissions.some((a: IViewPermission) =>\r\n a.permission == eViewPermission.viewQuoteHeader),\r\n canViewDiscount: this.$scope.model.userViewPermissions.some((a: IViewPermission) =>\r\n a.permission == eViewPermission.viewDiscount),\r\n canViewCost: this.$scope.model.userViewPermissions.some((a: IViewPermission) =>\r\n a.permission == eViewPermission.viewCost),\r\n canViewPricing: this.$scope.model.userViewPermissions.some((a: IViewPermission) =>\r\n a.permission == eViewPermission.viewPricing),\r\n canViewCustomer: this.$scope.model.userViewPermissions.some((a: IViewPermission) =>\r\n a.permission == eViewPermission.viewCustomer),\r\n canViewCurrency: this.$scope.model.userViewPermissions.some((a: IViewPermission) =>\r\n a.permission == eViewPermission.viewCurrency),\r\n canViewShipping: this.$scope.model.userViewPermissions.some((a: IViewPermission) =>\r\n a.permission == eViewPermission.viewShipping),\r\n canModifyQuoteProductDescription: this.canUserPerformAction(eWorkflowAction.modifyQuoteProductDescription),\r\n canViewQuoteProductDetails: this.$scope.model.userViewPermissions.some((a: IViewPermission) =>\r\n a.permission == eViewPermission.viewQuoteProductDetails)\r\n };\r\n } else {\r\n this.$scope.permissions = {\r\n canModifyName: true,\r\n canModifyProducts: true,\r\n canModifyCustomer: this.$rootScope.user.canSetQuoteCustomer,\r\n canModifyDiscount: this.$rootScope.user.canSetQuoteDiscount,\r\n canAddAttachments: this.$rootScope.user.canAddAttachments,\r\n canModifyAttachments: this.$rootScope.user.canModifyAllAttachments,\r\n canModifyShipping: this.$rootScope.user.canSetQuoteShipping,\r\n canModifyQuoteHeader: true,\r\n canModifyCurrency: this.$rootScope.user.canSetQuoteCurrency,\r\n canReorderProducts: true,\r\n canViewQuoteHeader: this.$rootScope.user.canViewQuoteHeader,\r\n canViewDiscount: this.$rootScope.user.canViewQuoteDiscount,\r\n canViewCost: this.$rootScope.user.canViewCost,\r\n canViewPricing: this.$rootScope.user.canViewPrices,\r\n canViewCustomer: this.$rootScope.user.canViewQuoteCustomer || this.$rootScope.user.canSetQuoteCustomer,\r\n canViewCurrency: this.$rootScope.user.canViewQuoteCurrency,\r\n canViewShipping: this.$rootScope.user.canViewQuoteShipping,\r\n canModifyQuoteProductDescription: this.$rootScope.user.canSetQuoteProductDescription,\r\n canViewQuoteProductDetails: true\r\n };\r\n }\r\n\r\n this.$scope.productSortableOptions.disabled = !this.$scope.permissions.canReorderProducts;\r\n\r\n if (!this.$scope.permissions.canViewQuoteHeader) {\r\n this.$scope.selectedTab = null;\r\n }\r\n }\r\n\r\n private validate(): boolean {\r\n let model = this.$scope.model;\r\n this.$scope.validationMessages = [];\r\n this.$scope.v.validation = {\r\n products: {}\r\n };\r\n let validation = this.$scope.v.validation;\r\n let result = true;\r\n if (!model.name) {\r\n this.$scope.validationMessages.push({\r\n messageType: eValidationType.error,\r\n message: \"Quote is missing a name\",\r\n propertyName: \"name\",\r\n object: {\r\n name: \"Quote\"\r\n }\r\n });\r\n validation.name = \"Please enter a name\";\r\n result = false;\r\n }\r\n\r\n let productError = (index: number, field: string, msg: string, includeInValidationMessages: boolean = true) => {\r\n if (!validation.products[index]) validation.products[index] = {};\r\n validation.products[index][field] = msg;\r\n if (includeInValidationMessages) {\r\n this.$scope.validationMessages.push({\r\n messageType: eValidationType.error,\r\n message: msg,\r\n propertyName: \"Product \" + model.products[index].name,\r\n object: {\r\n id: model.products[index].id.toString(),\r\n name: \"Product \" + model.products[index].name\r\n }\r\n });\r\n }\r\n result = false;\r\n };\r\n\r\n let getErrors = (configProd: IConfiguredProduct, name: string) => {\r\n if (configProd.validationMessages) {\r\n configProd.validationMessages.forEach(err => this.$scope.validationMessages.push(err));\r\n }\r\n if (configProd.configurators) {\r\n configProd.configurators.forEach(c => getErrors(c, name));\r\n }\r\n };\r\n\r\n model.headerValues = this.$scope.defConfig.getConfiguredProduct();\r\n\r\n getErrors(model.headerValues, \"Header\");\r\n\r\n model.products.forEach((product: IQuoteProduct, i: number) => {\r\n if (product.isConfigured && product.configuredProduct.hasErrors) {\r\n productError(i, \"name\", \"Please correct the configurator errors.\", false);\r\n getErrors(product.configuredProduct, \"Product \" + product.name);\r\n }\r\n if (!product.allowFractionalQty && product.qty % 1 != 0) {\r\n productError(i, \"qty\", \"Must be whole number\");\r\n }\r\n let maxDiscount = Math.min(product.maxDiscountPercentage, 100);\r\n if (product.discountPercentage > maxDiscount) {\r\n productError(i, \"discountPercentage\", \"Must be less than \" + maxDiscount + \"%\");\r\n }\r\n if (product.maxQty && product.qty > product.maxQty) {\r\n productError(i, \"qty\", \"Limited to \" + product.maxQty);\r\n }\r\n if ((product.minQty && product.qty < product.minQty) || product.qty < 1) {\r\n productError(i, \"qty\", \"Must be at least \" + Math.max(product.minQty, 1));\r\n }\r\n });\r\n\r\n return result &&\r\n (\r\n !model.headerValues ||\r\n !model.headerValues.validationMessages ||\r\n !model.headerValues.validationMessages.some(m => m.messageType == eValidationType.error)\r\n );\r\n }\r\n\r\n private submit() {\r\n /*if (this.$rootScope.user.id == authService.ANONYMOUS_USER_ID) {\r\n this.dialogService.alert({\r\n type: eAlertType.info,\r\n msg: \"Before you can submit this quote, please login or register.\"\r\n });\r\n \r\n this.$rootScope.user = null;\r\n this.$rootScope.$broadcast(kb.events.loginRequested);\r\n this.submitQuotePending = true;\r\n return;\r\n }*/\r\n this.$scope.model.headerValues = this.$scope.defConfig.getConfiguredProduct();\r\n if (this.validate() ||\r\n this.$rootScope.context.companySettings.allowInvalidQuotesInWorkflow\r\n ) {\r\n this.$scope.executeAction(eWorkflowAction.submit).then(() => {\r\n this.$location.url(\"/quotes/\" + this.$scope.model.id);\r\n this.bypassUnsavedConfirmation = true;\r\n });\r\n } else this.promptUserToFixErrors();\r\n }\r\n\r\n public runRuleCycleUnit(config: Configurator, field: Field, bubble = true): ng.IPromise {\r\n // Skip the entire cycle if user can't view the quote header, since doing so is wasteful.\r\n if (!this.$scope.permissions.canViewQuoteHeader) return this.$q.all([]);\r\n let ruleArgs = this.getRuleArgs(config, field);\r\n let runRules =\r\n this.helper.runSelects(config)\r\n // value rules\r\n .then(() =>\r\n this.helper.runRuleTypeAsync(config, eRuleType.value, ruleArgs)\r\n ).then(() =>\r\n // reset $fieldsDirty of this configurator so it doesn't affect \r\n // a parent's decision on whether to run the child's rules\r\n config.$fieldsDirty = false\r\n ).then(() =>\r\n this.runValidationRule(config, ruleArgs)\r\n ).then(() =>\r\n this.helper.runRuleTypeAsync(config, eRuleType.visibility, ruleArgs)\r\n ).then(() => {\r\n this.$scope.visiblePages = config.pages.filter((p) => p.visible);\r\n if (!this.$scope.model.idWorkflow &&\r\n this.$scope.defConfig.hasQuoteRule\r\n ) {\r\n // run the quote rule if we are not in a workflow \r\n // (in a workflow it get's run the by the action on the server)\r\n this.$scope.model.headerValues = this.$scope.defConfig.getConfiguredProduct();\r\n return this.api.quotes.runQuoteHeaderRule(\r\n this.$scope.model,\r\n this.$rootScope.contentTracker\r\n ).then(q => {\r\n this.setUpdatedModelInternal(q, false);\r\n });\r\n }\r\n });\r\n\r\n return runRules;\r\n }\r\n\r\n public getRuleArgs(config: Configurator, changedField?: Field): QuoteHeaderRuleArgs {\r\n let ruleArgs = new QuoteHeaderRuleArgs(this);\r\n ruleArgs.user = this.$rootScope.user;\r\n ruleArgs.environment = this.$rootScope.environment;\r\n ruleArgs.baseUrl = this.$rootScope.context.baseUrl;\r\n ruleArgs.configurator = config;\r\n ruleArgs.kom = config.$manager;\r\n ruleArgs.parentKom = config.$parentConfigurator ? config.$parentConfigurator.$manager : null;\r\n ruleArgs.changedField = changedField;\r\n ruleArgs.quote = this.$scope.model;\r\n ruleArgs.logs = new ClientLogger();\r\n ruleArgs.clientLanguage = this.$rootScope.clientLanguage;\r\n if (this.$rootScope.context.sfdcCanvasRequest) {\r\n // combine query string parameters with sfdc parameters\r\n ruleArgs.parameters = Utils.extend(\r\n this.$rootScope.context.sfdcCanvasRequest.context.environment.parameters,\r\n this.$location.search()\r\n );\r\n } else {\r\n ruleArgs.parameters = this.$location.search();\r\n }\r\n\r\n return ruleArgs;\r\n }\r\n\r\n /**\r\n * starts a configurator by loading any tables it references and running the rules once\r\n * @param config\r\n */\r\n public startConfigurator(): ng.IPromise {\r\n let tableIds = this.header.references.filter(r => r.type.isEqual(\"Table\")).map(r => r.id);\r\n return this.helper.downloadTables(tableIds)\r\n .then(() => this.runRuleCycleUnit(this.$scope.defConfig, null));\r\n }\r\n\r\n private startValidationTimer() {\r\n if (!this._stopValidationTimer) {\r\n this._stopValidationTimer = this.$interval(() => {\r\n this.validate();\r\n }, 1000);\r\n }\r\n }\r\n\r\n private stopValidationTimer() {\r\n this.$interval.cancel(this._stopValidationTimer);\r\n this._stopValidationTimer = null;\r\n }\r\n\r\n public handleActionResponse(result: IQuote, actionType: string) {\r\n this.setUpdatedModelInternal(result, false);\r\n if (\r\n actionType == eWorkflowAction.submit\r\n && !this.$rootScope.isSfdc\r\n && !result.allowedActions.some(a => a.type == eWorkflowAction.modifyProducts) //only clear the active quote if the user no longer has modify product permissions\r\n ) {\r\n this.quoteService.quote = null;\r\n } else {\r\n // if this is the active quote, then refresh the active quote data to keep it in sync\r\n if (this.quoteService.quote && result && this.quoteService.quote.id === result.id) {\r\n this.quoteService.quote = result;\r\n }\r\n }\r\n if (this.$scope.isNew) { // change to edit edit screen if we were on the new screen before\r\n this.quoteService.quote = result;\r\n this.$state.go(\"kb.quoteEdit\", { id: this.$scope.model.id });\r\n } else {\r\n this.refreshDrawers();\r\n }\r\n\r\n // refresh the comments as sometimes they are added server-side (like for rejection reasons)\r\n this.$scope.commentListApi.refresh();\r\n this.refreshPermissions();\r\n this.validate();\r\n this.markChangesClean();\r\n }\r\n\r\n private revertToClean() {\r\n this.setUpdatedModelInternal(angular.copy(this.cleanModel), false);\r\n }\r\n\r\n private promptUserToFixErrors() {\r\n this.dialogService.alert({ type: eAlertType.error, template: Dirs.view(\"alert-quote-errors\") });\r\n }\r\n\r\n public runValidationRule(config: Configurator, ruleArgs: IConfiguratorRuleArgs): ng.IPromise {\r\n config.preValidate(); // call internal validation for fields\r\n return this.helper.runRuleTypeAsync(config, eRuleType.validation, ruleArgs).then(() => {\r\n config.isValid(); //force recalculation of $valid property\r\n });\r\n }\r\n}\r\n","import { NgView } from '@app/di/decorators';\r\nimport { Token } from '@app/di/token';\r\nimport { ApiService } from '@app/services/api.service';\r\nimport { QuoteService } from '@app/services/quote.service';\r\nimport { SearchService } from '@app/services/search.service';\r\nimport { StorageService } from '@app/services/storage.service';\r\nimport { UploadService } from '@app/services/upload.service';\r\nimport { ISearchScope, SearchController } from '@app/views/search.view';\r\nimport {\r\n IFilter,\r\n IQuote,\r\n IQuoteFile,\r\n IQuoteProduct,\r\n IRootScope,\r\n ISavedSearch,\r\n eFieldType,\r\n eFileSource,\r\n eFilterControl,\r\n eFilterSource,\r\n eFilterType,\r\n meta,\r\n} from '@models';\r\nimport { icons } from '@tools';\r\nimport Big from 'big.js';\r\n\r\nexport interface IQuotesScope extends ISearchScope {\r\n downloadAttachment: (file: IQuoteFile) => void;\r\n openProduct: (idQuote: number, p: IQuoteProduct) => void;\r\n getFirstProductImage: (quote: IQuote) => string;\r\n // filterJson: string;\r\n getTotalPrice: (quote: IQuote) => Big;\r\n fieldChange: (filter: IFilter) => void;\r\n}\r\n\r\n@NgView({\r\n token: Token.QuotesView,\r\n inherit: [Token.SearchView],\r\n dependencies: [Token.$RootScope, Token.UploadService, Token.QuoteService, Token.StorageService],\r\n})\r\nexport class QuotesController extends SearchController {\r\n constructor(\r\n $scope: IQuotesScope,\r\n agg: SearchService,\r\n $rootScope: IRootScope,\r\n private upload: UploadService,\r\n private quoteService: QuoteService,\r\n private storageService: StorageService\r\n ) {\r\n super($scope, agg);\r\n\r\n agg.drawerService.setHelpUrl('Quotes');\r\n agg.drawerService.pageType = loc.quotes;\r\n agg.drawerService.pageIcon = icons.quote;\r\n\r\n $scope.savedSearchEnabled = true;\r\n this.refreshSavedSearches();\r\n\r\n if (this.agg.$rootScope.company.useDatabaseSearch) {\r\n $scope.availableFilters.pushArray([this.getWhereFieldFilter()]);\r\n }\r\n $scope.binding.search.modelType = meta.Quote.$name;\r\n $scope.modelTypes = [\r\n { type: meta.Quote.$name, label: 'Quotes', state: 'kb.quotes' },\r\n { type: meta.QuoteProduct.$name, label: 'Configured Products', state: 'kb.configuredProducts' },\r\n ];\r\n $scope.downloadAttachment = (file: IQuoteFile) => {\r\n if (file.source == eFileSource.media) {\r\n window.open(storageService.getMediaUrl(file.filePath));\r\n } else {\r\n window.open('api/quotes/file/download/' + file.id, '_blank');\r\n }\r\n };\r\n $scope.openProduct = (idQuote: number, p: IQuoteProduct) => {\r\n if (p.isConfigured) {\r\n agg.$state.go('kb.configuredProduct', { id: p.id });\r\n } else {\r\n agg.$state.go('kb.product', { id: p.idProduct });\r\n }\r\n };\r\n $scope.getFirstProductImage = (quote: IQuote) => {\r\n let p = quote.products.find(p => p.imagePath != null);\r\n return p ? p.imagePath : null;\r\n };\r\n\r\n $scope.fieldChange = filter => {\r\n let field = this.$scope.filterSource[filter['$key']].find(f => f.name == filter.fieldName);\r\n let fieldType = field ? field.type : eFieldType.text;\r\n filter.fieldType = fieldType;\r\n if (fieldType == eFieldType.number) {\r\n filter.control = eFilterControl.numberRange;\r\n } else if (fieldType == eFieldType.boolean) {\r\n filter.control = eFilterControl.checkbox;\r\n } else {\r\n filter.control = eFilterControl.text;\r\n }\r\n };\r\n\r\n agg.drawerService.addDrawer(icons.add, loc.add, () => agg.$state.go('kb.quoteNew'));\r\n if ($rootScope.companySettings.enableQuoteImport) {\r\n agg.drawerService.addDrawer(icons.upload, 'Import', () => this.import());\r\n }\r\n agg.drawerService.addDrawer(icons.clone, loc.clone, () => this.clone());\r\n agg.drawerService.addDrawer(icons.deleter, loc.deleter, () => this.deleteItems());\r\n }\r\n\r\n public import() {\r\n this.upload.promptUserToChooseFile().then(file => {\r\n let formData = new FormData();\r\n formData.append('file', file);\r\n this.upload.uploadFile(formData, '/api/quotes/import').then(r => {\r\n this.agg.$state.go('kb.quoteEdit', { id: r.id });\r\n });\r\n });\r\n }\r\n\r\n public client(api: ApiService) {\r\n return api.quotes;\r\n }\r\n public newSearch(): ISavedSearch {\r\n return {\r\n modelType: meta.Quote.$name,\r\n sortField: meta.Quote.modifiedDate.name, // \"modifiedDate\",\r\n descending: true,\r\n filters: this.getFiltersFromMeta(meta.Quote.$name, true),\r\n roles: [],\r\n };\r\n }\r\n\r\n protected onItemsDeleted(items: IQuote[]) {\r\n //empty out the active quote if we just deleted it\r\n for (let q of items) {\r\n if (q && this.quoteService.quote && q.id == this.quoteService.quote.id) {\r\n this.quoteService.quote = null;\r\n }\r\n }\r\n }\r\n\r\n public getWhereFieldFilter(): IFilter {\r\n return {\r\n type: eFilterType.headerValue,\r\n label: 'Where Header Field',\r\n fieldName: null,\r\n control: eFilterControl.none,\r\n sourceType: eFilterSource.headerFields,\r\n values: [null],\r\n };\r\n }\r\n}\r\n","import { DialogService } from \"@app/services/dialog.service\";\r\nimport { CrudController, ICrudScope } from \"@app/views/crud.view\";\r\nimport { NgView } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { IKbUserEdit, IPasswordChange } from \"@models\";\r\nimport { IRootScope } from \"@models\";\r\nimport { icons } from \"@tools\";\r\nimport { AuthService } from \"@app/services/auth.service\";\r\nimport { KbService } from \"@app/services/kb.service\";\r\nimport { DrawerService } from \"@app/services/drawer.service\";\r\nimport { SignalrService } from \"@app/services/signalr.service\";\r\nimport { ApiService } from \"@app/services/api.service\";\r\nimport { CrudService } from \"@app/services/crud.service\";\r\n\r\nexport interface IChangePasswordScope extends ICrudScope {\r\n kbUser: IKbUserEdit;\r\n}\r\n\r\n@NgView({\r\n token: Token.ChangePasswordView,\r\n inherit: [Token.CrudView],\r\n dependencies: [\r\n Token.$Scope,\r\n Token.CrudService\r\n ]\r\n})\r\nexport class ChangePasswordController extends CrudController {\r\n\r\n constructor(\r\n $scope: IChangePasswordScope,\r\n crudService: CrudService\r\n ) {\r\n\r\n super(\r\n $scope,\r\n crudService,\r\n { id: crudService.$stateParams.id } as any\r\n );\r\n\r\n $scope.model = { id: this.$stateParams.id } as any;\r\n this.drawerService.setHelpUrl(null);\r\n\r\n // add drawers\r\n let drSave = this.drawerService.addDrawer(icons.save, loc.save, $scope.save);\r\n let drCancel = this.drawerService.addDrawer(icons.cancel, loc.cancel, $scope.cancel);\r\n }\r\n\r\n public client(api: ApiService) {\r\n return api.changePassword;\r\n }\r\n\r\n public onSuccess() {\r\n this.$state.go(\"kb.admin.userEdit\", { id: this.$stateParams.id });\r\n }\r\n\r\n}\r\n","import { NgView } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { ApiService } from \"@app/services/api.service\";\r\nimport { CrudService } from \"@app/services/crud.service\";\r\nimport { KbService } from \"@app/services/kb.service\";\r\nimport { CrudController, ICrudScope } from \"@app/views/crud.view\";\r\nimport { IKbRole, IKbUserEdit, INameValue, INotificationSetting, eAlertType, eNotificationSetting, eViewType, IRootScope, eUserLicenseType } from \"@models\";\r\nimport { icons } from \"@tools\";\r\n\r\nexport interface IUserScope extends ICrudScope {\r\n canResetPassword: boolean;\r\n canChangePassword: boolean;\r\n resetPassword: () => void;\r\n canEdit: boolean;\r\n roles: IKbRole[];\r\n notificationOptions: INameValue[];\r\n pendingApprovalNotificationOptions: INameValue[];\r\n notificationSetting: INotificationSetting;\r\n deleteAndAnonymize: () => void;\r\n isReadOnlySso: boolean;\r\n resetDeactivation: () => void;\r\n channels: INameValue[];\r\n}\r\n\r\n@NgView({\r\n token: Token.UserView,\r\n inherit: [Token.CrudView],\r\n dependencies: [\r\n Token.$RootScope,\r\n Token.KbService\r\n ]\r\n})\r\nexport class UserController extends CrudController {\r\n\r\n constructor(\r\n public $scope: IUserScope,\r\n crudService: CrudService,\r\n model: IKbUserEdit,\r\n public $rootScope: IRootScope,\r\n kbService: KbService\r\n ) {\r\n super(\r\n $scope,\r\n crudService,\r\n model\r\n );\r\n\r\n $scope.isReadOnlySso = !$rootScope.context.ssoManualUserManagement && model.isSsoUser;\r\n\r\n this.drawerService.setHelpUrl(\"Users\");\r\n\r\n this.$http.get(\"/api/notificationsettings\").then(response => {\r\n $scope.notificationSetting = response.data;\r\n });\r\n\r\n if ($rootScope.user.isCompanyAdmin) {\r\n this.api.channels.search({\r\n sortField: \"name\"\r\n }).then(channels => {\r\n $scope.channels = channels.map(c => {\r\n return {\r\n name: c.name,\r\n value: c.id.toString()\r\n };\r\n });\r\n $scope.channels.unshift({\r\n name: \"-None-\",\r\n value: null\r\n });\r\n });\r\n }\r\n\r\n if (this.$state.current.data.viewType == eViewType.new) {\r\n // create a new blank user\r\n $scope.model = {\r\n isApproved: true,\r\n licenseType: eUserLicenseType.internal,\r\n shipToBillingAddress: true,\r\n roles: []\r\n };\r\n }\r\n\r\n this.api.roles.search({\r\n sortField: \"role\",\r\n }).then(r => {\r\n $scope.roles = r.filter(ur => ur.id != -1);\r\n });\r\n\r\n $scope.resetDeactivation = () => {\r\n this.api.users.resetDeactivation(this.$stateParams.id).then(() => {\r\n this.dialogService.alert({\r\n type: eAlertType.success,\r\n msg: loc.msg_resetdeactivationcomplete\r\n });\r\n });\r\n }\r\n\r\n $scope.resetPassword = () => {\r\n this.api.users.resetPassword(this.$stateParams.id).then(() => {\r\n this.dialogService.alert({\r\n type: eAlertType.success,\r\n msg: loc.msg_passwordreset.format($scope.model.email)\r\n });\r\n });\r\n };\r\n\r\n $scope.deleteAndAnonymize = () => {\r\n this.dialogService.confirm(\"Are you sure you want to delete and permanently anonymize this user? This cannot be undone!\", () => {\r\n this.api.users.deleteAndAnonymize(this.$stateParams.id).then(() => {\r\n this.$state.go(\"kb.admin.users\");\r\n });\r\n });\r\n }\r\n\r\n this.deleteMsg = loc.msg_deleteuser.format(this.$scope.model.firstName + \" \" + this.$scope.model.lastName);\r\n\r\n $scope.canEdit = false;\r\n $scope.canResetPassword = false;\r\n $scope.canChangePassword = false;\r\n\r\n // determine whether to show edit buttons\r\n if (this.$rootScope.user.id == this.$stateParams.id) {\r\n // if (this.$rootScope.user.canModifySelf) {\r\n this.$scope.canEdit = true;\r\n this.$scope.canChangePassword = true;\r\n // }\r\n } else {\r\n if (this.$rootScope.user.canModifyUsers) {\r\n this.$scope.canEdit = true;\r\n this.$scope.canResetPassword = true;\r\n }\r\n }\r\n\r\n $scope.notificationOptions = kbService.getEnumSelects(eNotificationSetting, \"eNotificationSetting\");\r\n $scope.pendingApprovalNotificationOptions = [\r\n {\r\n name: loc.enotificationsetting_email_title,\r\n value: eNotificationSetting.email\r\n },\r\n {\r\n name: loc.enotificationsetting_none_title,\r\n value: eNotificationSetting.none\r\n },\r\n {\r\n name: loc.enotificationsetting_companydefault_title,\r\n value: eNotificationSetting.companyDefault\r\n },\r\n ];\r\n\r\n // add drawers\r\n let drChangePassword = this.drawerService.addDrawer(icons.change, loc.changepassword, () => {\r\n this.$state.go(\"kb.changePassword\", { id: $scope.model.id });\r\n }, $scope.canChangePassword && !$scope.isNew);\r\n if (!$scope.model.isSsoUser) {\r\n let drResetPassword = this.drawerService.addDrawer(\r\n icons.change,\r\n loc.resetpassword,\r\n $scope.resetPassword,\r\n $scope.canResetPassword && !$scope.isNew\r\n );\r\n }\r\n let drEdit = this.drawerService.addDrawer(icons.edit, loc.edit, () => {\r\n this.$state.go(\"kb.admin.userEdit\", { id: $scope.model.id });\r\n }, $scope.canEdit && $scope.isView);\r\n let drDelete = this.drawerService.addDrawer(\r\n icons.deleter,\r\n loc.deleter,\r\n $scope.delete,\r\n $scope.canEdit && !$scope.isNew\r\n );\r\n let drDeleteAndAnonymize = this.drawerService.addDrawer(\r\n icons.anonymize,\r\n loc.deleteandanonymize,\r\n $scope.deleteAndAnonymize,\r\n $scope.canEdit && !$scope.isNew\r\n );\r\n let drResetDeactivations = this.drawerService.addDrawer(\r\n icons.action, loc.resetdeactivationtimer, $scope.resetDeactivation, $rootScope.companySettings.accountIdleExpirationInDays > 0 && $scope.isEdit && $rootScope.context.user.canModifyUsers);\r\n let drSave = this.drawerService.addDrawer(\r\n icons.save, loc.save, $scope.save, $scope.isEdit || $scope.isNew);\r\n let drCancel = this.drawerService.addDrawer(\r\n icons.cancel, loc.cancel, $scope.cancel, $scope.isEdit || $scope.isNew);\r\n }\r\n\r\n public client(api: ApiService) {\r\n return api.users;\r\n }\r\n\r\n public waitForRefresh() {\r\n return true;\r\n }\r\n\r\n public onSuccess() {\r\n if (this.$rootScope.user.isCompanyAdmin) {\r\n this.$state.go(\"kb.admin.users\");\r\n } else {\r\n this.$state.go(\"kb.products\");\r\n }\r\n }\r\n\r\n public onDelete() {\r\n this.$state.go(\"kb.admin.users\");\r\n }\r\n\r\n}\r\n","import { DI } from \"@app/di/decorators\";\r\nimport { Token } from \"@app/di/token\";\r\nimport { eBundle } from \"@app/helpers/dirs\";\r\nimport { StateHelper } from \"@app/helpers/state.helper\";\r\nimport \"@app/index\"; // make sure app.js is the last thing in the bundle\r\nimport { AuthService } from \"@app/services/auth.service\";\r\nimport { BundleLoaderService } from \"@app/services/bundle-loader.service\";\r\nimport { TelemetryService } from \"@app/services/telemetry.service\";\r\nimport { ThemeService } from \"@app/services/theme.service\";\r\nimport { eViewType, IProductTranslation, IRootScope, ITranslation } from \"@models\";\r\nimport { icons, Utils } from \"@tools\";\r\nimport { StateProvider, StateService, Transition, UrlRouterProvider } from \"@uirouter/angularjs\";\r\nimport * as angular from \"angular\";\r\nimport { ApiService } from \"./services/api.service\";\r\nimport { QuoteService } from \"./services/quote.service\";\r\nimport { SfdcService } from \"./services/sfdc.service\";\r\nexport * from \"@app/index\";\r\n\r\nangular.module('appTemplates', []);\r\n\r\nexport let kbapp: ng.IModule = angular.module(\"kbapp\",\r\n [\r\n \"ngAnimate\",\r\n \"ngCookies\",\r\n \"ngSanitize\",\r\n \"ui.router\",\r\n \"ajoslin.promise-tracker\",\r\n \"ui.sortable\",\r\n \"oc.lazyLoad\",\r\n \"appTemplates\",\r\n \"text-mask\"\r\n // \"jcs.angular-http-batch\"\r\n ]);\r\n\r\nDI.fillAngularApp(kbapp);\r\n\r\nkbapp.config([\r\n \"$locationProvider\",\r\n \"$stateProvider\",\r\n \"$httpProvider\",\r\n \"$urlRouterProvider\",\r\n \"$provide\",\r\n \"$animateProvider\",\r\n // \"httpBatchConfigProvider\",\r\n \"$compileProvider\",\r\n (\r\n $locationProvider: ng.ILocationProvider,\r\n $stateProvider: StateProvider,\r\n $httpProvider: ng.IHttpProvider,\r\n $urlRouterProvider: UrlRouterProvider,\r\n $provide: ng.auto.IProvideService,\r\n $animateProvider: ng.animate.IAnimateProvider,\r\n // httpBatchConfigProvider: any,\r\n $compileProvider: ng.ICompileProvider\r\n ) => {\r\n // don't use hashbang mode\r\n $locationProvider.html5Mode(true);\r\n\r\n // Remove the header used to identify ajax call that would prevent CORS from working\r\n delete $httpProvider.defaults.headers.common[\"X-Requested-With\"];\r\n\r\n // turn off debug classes from angular for performance boost: \r\n // https://code.angularjs.org/1.5.5/docs/guide/production\r\n $compileProvider.debugInfoEnabled(false);\r\n $compileProvider.commentDirectivesEnabled(false);\r\n $compileProvider.cssClassDirectivesEnabled(false);\r\n\r\n // add our http interceptors\r\n $httpProvider.interceptors.push(\"securityInterceptor\");\r\n $httpProvider.interceptors.push(\"cacheBusterInterceptor\");\r\n\r\n // $httpProvider.useApplyAsync(true);\r\n // $httpProvider.interceptors.push(\"errorInterceptor\");\r\n\r\n $provide.decorator(\"$exceptionHandler\", [\"$delegate\", Token.$Injector.key, ($delegate: ng.IExceptionHandlerService, $injector: ng.auto.IInjectorService) => {\r\n return ((exception, cause) => {\r\n $delegate(exception, cause);\r\n let $telemetryService = $injector.get(Token.TelemetryService.key) as TelemetryService;\r\n $telemetryService.trackException(exception);\r\n }) as ng.IExceptionHandlerService;\r\n }]);\r\n\r\n // when we are on the sfdc url, then go to whatever path the sfdc canvas asked for\r\n $urlRouterProvider.when(\"/sfdc\", [\r\n Token.$Location.key, Token.$RootScope.key, Token.$State.key, ($location: ng.ILocationService, $rootScope: IRootScope, $state: StateService) => {\r\n let isSfdcCpq = $rootScope.context.sfdcCanvasRequest.context.environment.parameters.sfdccpq;\r\n if (isSfdcCpq) {\r\n let queryString = $location.search();\r\n \r\n if (queryString['idtheme']) {\r\n return `/configurators/1?idtheme=${queryString['idtheme']}`;\r\n }\r\n // we use a dummy configurator id here. The configuratorController will \r\n // communicate through the canvas to get the real id\r\n return \"/configurators/1\";\r\n } else {\r\n let path = $rootScope.context.sfdcCanvasRequest.context.environment.parameters.path;\r\n path = path || \"/products\";\r\n return path;\r\n }\r\n }]);\r\n // $urlRouterProvider.when(\"/sfdc/\", handleSfdcUrl);\r\n\r\n // defult to products page\r\n $urlRouterProvider.when(\"/\", [\r\n \"$location\", \"$rootScope\", ($location: ng.ILocationService, $rootScope: IRootScope) => {\r\n if (!$rootScope.company.licenseKbmax && $rootScope.company.license3D) {\r\n return \"/admin/scenes\";\r\n }\r\n return \"/products\";\r\n }]);\r\n\r\n $urlRouterProvider.when(\"/admin\", [\r\n \"$location\", \"$rootScope\", ($location: ng.ILocationService, $rootScope: IRootScope) => {\r\n if ($rootScope.company.licenseKbmax) {\r\n if ($rootScope.user.canModifyProducts) {\r\n return \"/admin/configurators\";\r\n } else if ($rootScope.user.canModifyScenes && $rootScope.company.license3D) {\r\n return \"/admin/scenes\";\r\n } else if ($rootScope.user.canModifyUsers || $rootScope.user.isChannelAdmin) {\r\n return \"/admin/users\";\r\n } else if ($rootScope.user.canModifyCurrencies) {\r\n return \"/admin/currencies\";\r\n } else if ($rootScope.user.canModifyMedia) {\r\n return \"/admin/media\";\r\n }\r\n } else {\r\n if ($rootScope.company.license3D) {\r\n return \"/admin/scenes\";\r\n }\r\n }\r\n return \"/\";\r\n }]);\r\n $urlRouterProvider.otherwise(\"/\");\r\n\r\n // only run animations on elements that have a kb-animate class name. \r\n // This should increase performance.See here: https://docs.angularjs.org/api/ng/provider/$animateProvider\r\n $animateProvider.classNameFilter(/kb-animate/);\r\n\r\n // register the api batch handler\r\n // httpBatchConfigProvider.setAllowedBatchEndpoint(\"/api\", \"/api/batch\", {\r\n // maxBatchedRequestPerCall: 10,\r\n // minimumBatchSize: 2,\r\n // batchRequestCollectionDelay: 100,\r\n // ignoredVerbs: [\"head\"],\r\n // sendCookies: false,\r\n // enabled: true,\r\n // // defaults to this value we currently also support a node js multifetch format as well\r\n // adapter: \"httpBatchAdapter\"\r\n // });\r\n\r\n let stateHelper = new StateHelper($stateProvider, eBundle.app);\r\n\r\n // setup states using ui-router library\r\n stateHelper.addState({\r\n name: \"kb\",\r\n url: null,\r\n abstract: true,\r\n view: Token.PortalView,\r\n templateName: \"portal\"\r\n });\r\n stateHelper.addState({\r\n name: \"kb.login\",\r\n view: Token.LoginView,\r\n data: { onLoginPage: true }\r\n });\r\n stateHelper.addSearchState({\r\n name: \"kb.products\",\r\n view: Token.ProductsView,\r\n url: `/products?imagemode&search&searchid`\r\n });\r\n // stateHelper.addState({\r\n // name: \"kb.products\",\r\n // url: \"/products?cat&sort&q&mode\",\r\n // view: Token.ProductsView\r\n // });\r\n stateHelper.addState({\r\n name: \"kb.product\",\r\n url: \"/products/:id\",\r\n view: Token.ProductView\r\n });\r\n stateHelper.addState({\r\n name: \"kb.productCompare\",\r\n url: \"/productcompare/:ids\",\r\n view: Token.ProductCompareView,\r\n params: {\r\n ids: { array: true }\r\n }\r\n });\r\n stateHelper.addState({\r\n name: \"kb.configurator\",\r\n url: \"/configurators/:id\",\r\n data: { viewType: eViewType.new },\r\n view: Token.ConfiguratorView\r\n });\r\n stateHelper.addState({\r\n name: \"kb.configuredProduct\",\r\n url: \"/quoteproducts/:id\",\r\n templateName: \"configurator\",\r\n data: { viewType: eViewType.edit },\r\n view: Token.ConfiguratorView\r\n });\r\n stateHelper.addState({\r\n name: \"kb.configuratorTest\",\r\n url: \"/configurators/test/:id\",\r\n templateName: \"configurator\",\r\n data: { viewType: eViewType.new, isTest: true },\r\n view: Token.ConfiguratorView\r\n });\r\n stateHelper.addCrudStates({\r\n name: \"kb.quote\",\r\n view: Token.QuoteView,\r\n searchView: Token.QuotesView\r\n });\r\n stateHelper.addSearchState({\r\n name: \"kb.configuredProducts\",\r\n view: Token.ConfiguredProductsView\r\n });\r\n stateHelper.addCrudStates({\r\n name: \"kb.customer\",\r\n view: Token.CustomerView,\r\n searchView: Token.CustomersView\r\n });\r\n stateHelper.addCrudStates({\r\n name: \"kb.contact\",\r\n view: Token.ContactView,\r\n searchView: Token.ContactsView\r\n });\r\n stateHelper.addState({\r\n name: \"userActivation\",\r\n url: \"/users/activate/?idUser&activationGuid&pass&new\",\r\n view: Token.UserActivationView,\r\n allowAnonymous: true\r\n });\r\n stateHelper.addState({\r\n name: \"kb.changePassword\",\r\n url: \"/users/changepassword/:id\",\r\n data: { viewType: eViewType.new },\r\n view: Token.ChangePasswordView\r\n });\r\n stateHelper.addState({\r\n name: \"kb.notifications\",\r\n url: \"/notifications?q&sort&desc\",\r\n view: Token.NotificationsView\r\n });\r\n stateHelper.addState({\r\n name: \"scene\",\r\n url: \"/scenes/:id?requestid&&showmove\",\r\n view: Token.ConfiguratorView,\r\n templateName: \"configurator\",\r\n allowAnonymous: true\r\n });\r\n\r\n $stateProvider.state(\"kb.admin.**\", {\r\n url: \"/admin\",\r\n lazyLoad: ($transition$: Transition) => {\r\n var bundleLoader = $transition$.injector().get(Token.BundleLoaderService.key) as BundleLoaderService;\r\n return bundleLoader.load([Token.AdminLib]) as any;\r\n }\r\n });\r\n }]);\r\n\r\nkbapp.run([\r\n Token.AuthService.key,\r\n Token.$RootScope.key,\r\n Token.$Http.key,\r\n Token.PromiseTracker.key,\r\n Token.$Location.key,\r\n Token.$State.key,\r\n Token.$Window.key,\r\n Token.ThemeService.key,\r\n Token.TelemetryService.key,\r\n Token.QuoteService.key,\r\n Token.ApiService.key,\r\n Token.SfdcService.key,\r\n (\r\n authService: AuthService,\r\n $rootScope: IRootScope,\r\n $http: ng.IHttpService,\r\n promiseTracker: ng.IPromiseTracker,\r\n $location: ng.ILocationService,\r\n $state: StateService,\r\n $window: ng.IWindowService,\r\n themeService: ThemeService,\r\n telemetryService: TelemetryService,\r\n quoteService: QuoteService,\r\n apiService: ApiService,\r\n sfdcService: SfdcService\r\n ) => {\r\n\r\n // store the state service on the rootscope so views can bind to it\r\n $rootScope.$state = $state;\r\n\r\n $rootScope.baseUrl = \"https://\" + $(location).attr(\"host\");\r\n\r\n $rootScope.isEpicorEmployee = () => $rootScope.user.email.toLowerCase().endsWith(\"@kbmax.com\") || $rootScope.user.email.toLowerCase().endsWith(\"@epicor.com\");\r\n\r\n // track if we are in sfdc\r\n $rootScope.isSfdc = ($rootScope.context.sfdcCanvasRequest != null);\r\n if ($rootScope.isSfdc) {\r\n $rootScope.isSfdcCpq = $rootScope.context.sfdcCanvasRequest.context.environment.parameters.sfdccpq;\r\n let queryString = $location.search();\r\n\r\n $rootScope.isSfdcCustomTheme = false;\r\n if (queryString[\"idtheme\"]) {\r\n $rootScope.isSfdcCustomTheme = true;\r\n }\r\n\r\n }\r\n\r\n // icons array used as a source for some bindings\r\n $rootScope.icons = Object.values(icons);\r\n\r\n // set initial window size values\r\n let $win = $(window);\r\n $rootScope.windowWidth = $win.width();\r\n $rootScope.windowHeight = $win.height();\r\n\r\n // track the window size\r\n $(window).resize(() => {\r\n if (!$rootScope.$$phase) {\r\n $rootScope.$apply(() => {\r\n let $win = $(window);\r\n $rootScope.windowWidth = $win.width();\r\n $rootScope.windowHeight = $win.height();\r\n });\r\n }\r\n });\r\n\r\n $rootScope.contentTracker = promiseTracker();\r\n $rootScope.showSpinner = true;\r\n $rootScope.loginTracker = promiseTracker();\r\n $rootScope.infiniteScrollTracker = promiseTracker();\r\n $rootScope.isHoverSupported = !(matchMedia(\"(hover: none)\").matches);\r\n $rootScope.isIE = /msie\\s|trident\\//i.test(navigator.userAgent)\r\n $rootScope.comparedProducts = [];\r\n $rootScope.recaptchaToken = \"6LfFNOAUAAAAAAreoPer8J4F9qh9WLklfpUAbt28\";\r\n\r\n // hide browser address bar\r\n window.scrollTo(0, 1);\r\n\r\n $rootScope.translate = (entity, prop, realProp?) => {\r\n if (entity) {\r\n if ($rootScope.clientLanguage != $rootScope.companySettings.defaultLanguage) {\r\n if (entity && entity.translations && entity.translations.length) {\r\n let translation: IProductTranslation =\r\n (entity.translations as ITranslation[])\r\n .find(t => t.languageIso == $rootScope.clientLanguage);\r\n if (translation) {\r\n return translation.data[prop];\r\n }\r\n }\r\n }\r\n return entity[realProp || prop] || entity[prop];\r\n } else {\r\n return \"\";\r\n }\r\n };\r\n\r\n $rootScope.supportsFullscreen = !$rootScope.isSfdcCpq && Utils.supportsFullscreen();\r\n $rootScope.toggleFullscreen = () => {\r\n if ($rootScope.isSfdc) {\r\n sfdcService.toggleFullscreen();\r\n } else {\r\n Utils.toggleFullscreen();\r\n }\r\n };\r\n\r\n // track activity\r\n let lastMove = Date.now();\r\n let mouseMoveWait = false;\r\n window.onmousemove = (event) => {\r\n if (!mouseMoveWait) {\r\n lastMove = Date.now();\r\n\r\n mouseMoveWait = true;\r\n\r\n setTimeout(() => {\r\n mouseMoveWait = false;\r\n }, 200);\r\n }\r\n };\r\n\r\n const checkTime = 5 * 60000;\r\n setInterval(() => {\r\n if (Date.now() - lastMove < checkTime || $rootScope.user.isAnonymous)\r\n authService.keepAlive();\r\n }, checkTime);\r\n }]);\r\n"]}